IncludeCPP 4.0.2__py3-none-any.whl → 4.3.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.
@@ -0,0 +1,1757 @@
1
+ """
2
+ CSSL Multi-Language Support Module
3
+
4
+ Provides language definitions, syntax transformers, and cross-language instance access
5
+ for Python, Java, C#, C++, and JavaScript.
6
+
7
+ Usage:
8
+ @py = libinclude("python")
9
+ cpp = libinclude("c++")
10
+
11
+ define my_func() : supports @py {
12
+ # Python syntax here
13
+ for i in range(10):
14
+ print(i)
15
+ }
16
+
17
+ class MyClass : extends cpp$BaseClass {
18
+ // C++ style
19
+ }
20
+ """
21
+
22
+ from typing import Dict, List, Any, Optional, Callable
23
+ from dataclasses import dataclass, field
24
+ from enum import Enum
25
+ import re
26
+
27
+
28
+ class SupportedLanguage(Enum):
29
+ """Enumeration of supported programming languages"""
30
+ PYTHON = "python"
31
+ JAVA = "java"
32
+ CSHARP = "c#"
33
+ CPP = "c++"
34
+ JAVASCRIPT = "javascript"
35
+
36
+
37
+ @dataclass
38
+ class LanguageSyntax:
39
+ """Defines syntax rules for a programming language"""
40
+ name: str
41
+ statement_terminator: str # ";" or "\n"
42
+ uses_braces: bool # True for {}, False for indentation (Python)
43
+ boolean_true: str # "True", "true"
44
+ boolean_false: str # "False", "false"
45
+ null_keyword: str # "None", "null", "nullptr"
46
+ variable_keywords: List[str] # ["let", "const", "var"] for JS
47
+ function_keywords: List[str] # ["def"] for Python, ["function"] for JS
48
+ class_keywords: List[str] # ["class"]
49
+ constructor_name: str # "__init__" for Python, "constructor" for JS
50
+ print_function: str # "print", "console.log", "System.out.println"
51
+ comment_single: str # "#" or "//"
52
+ comment_multi_start: str # "/*" or '"""'
53
+ comment_multi_end: str # "*/" or '"""'
54
+
55
+
56
+ @dataclass
57
+ class LanguageSupport:
58
+ """
59
+ Language support object returned by libinclude().
60
+
61
+ Provides syntax transformation and cross-language instance sharing.
62
+ Now with real runtime bridges for C++, Java, and JavaScript (v4.1.1).
63
+ """
64
+ language: SupportedLanguage
65
+ syntax: LanguageSyntax
66
+ name: str
67
+ _instances: Dict[str, Any] = field(default_factory=dict)
68
+ _transformer: Optional['LanguageTransformer'] = field(default=None, repr=False)
69
+ _bridge: Optional['RuntimeBridge'] = field(default=None, repr=False)
70
+
71
+ def _get_bridge(self) -> Optional['RuntimeBridge']:
72
+ """Get the runtime bridge for this language."""
73
+ if self._bridge is not None:
74
+ return self._bridge
75
+
76
+ # Lazy-load the appropriate bridge
77
+ if self.language == SupportedLanguage.CPP:
78
+ self._bridge = get_cpp_bridge()
79
+ elif self.language == SupportedLanguage.JAVA:
80
+ self._bridge = get_java_bridge()
81
+ elif self.language == SupportedLanguage.JAVASCRIPT:
82
+ self._bridge = get_js_bridge()
83
+
84
+ return self._bridge
85
+
86
+ def share(self, name: str, instance: Any) -> None:
87
+ """
88
+ Share an instance for cross-language access.
89
+
90
+ Usage in CSSL:
91
+ cpp.share("Engine", myEngine)
92
+
93
+ Then accessible via:
94
+ cpp$Engine
95
+ """
96
+ self._instances[name] = instance
97
+ # Also share with the runtime bridge if available
98
+ bridge = self._get_bridge()
99
+ if bridge:
100
+ bridge.share(name, instance)
101
+
102
+ def get_instance(self, name: str) -> Any:
103
+ """
104
+ Get a shared instance by name with full bidirectional bridge support.
105
+
106
+ v4.1.1: Enhanced to access instances from runtime bridges.
107
+
108
+ Usage in CSSL:
109
+ engine = cpp.get("Engine")
110
+ // Or via $ syntax:
111
+ engine = cpp$Engine
112
+
113
+ For C++: Also accesses classes from IncludeCPP modules.
114
+ For Java: Accesses instances from JVM via JPype.
115
+ For JavaScript: Accesses instances from Node.js runtime.
116
+ """
117
+ # First check local instances
118
+ if name in self._instances:
119
+ return self._instances[name]
120
+
121
+ # Check the runtime bridge
122
+ bridge = self._get_bridge()
123
+ if bridge:
124
+ # Try to get from bridge's shared instances
125
+ instance = bridge.get_instance(name)
126
+ if instance is not None:
127
+ return instance
128
+
129
+ # C++ specific: Also check loaded modules for classes
130
+ if self.language == SupportedLanguage.CPP and hasattr(bridge, '_modules'):
131
+ for mod in bridge._modules.values():
132
+ if hasattr(mod, name):
133
+ cls_or_instance = getattr(mod, name)
134
+ # Cache for future access
135
+ self._instances[name] = cls_or_instance
136
+ return cls_or_instance
137
+
138
+ # Java specific: Try to load class by name
139
+ if self.language == SupportedLanguage.JAVA and hasattr(bridge, 'load_class'):
140
+ try:
141
+ cls = bridge.load_class(name)
142
+ if cls is not None:
143
+ self._instances[name] = cls
144
+ return cls
145
+ except Exception:
146
+ pass
147
+
148
+ # JavaScript specific: Try to get from JS context
149
+ if self.language == SupportedLanguage.JAVASCRIPT and hasattr(bridge, 'eval'):
150
+ try:
151
+ result = bridge.eval(f"typeof {name} !== 'undefined' ? {name} : null")
152
+ if result is not None:
153
+ self._instances[name] = result
154
+ return result
155
+ except Exception:
156
+ pass
157
+
158
+ return None
159
+
160
+ def has_instance(self, name: str) -> bool:
161
+ """Check if an instance is shared (includes bridge instances)."""
162
+ if name in self._instances:
163
+ return True
164
+ bridge = self._get_bridge()
165
+ if bridge:
166
+ if bridge.get_instance(name) is not None:
167
+ return True
168
+ # For C++, also check modules
169
+ if self.language == SupportedLanguage.CPP and hasattr(bridge, '_modules'):
170
+ for mod in bridge._modules.values():
171
+ if hasattr(mod, name):
172
+ return True
173
+ return False
174
+
175
+ def list_instances(self) -> List[str]:
176
+ """List all shared instance names (includes bridge instances and C++ classes)."""
177
+ return self.list_available()
178
+
179
+ def list_available(self) -> List[str]:
180
+ """
181
+ List all available items accessible via $ syntax.
182
+
183
+ v4.1.1: Enhanced to show all accessible items from runtime bridges.
184
+
185
+ Returns a list of names that can be used with lang$Name syntax.
186
+ """
187
+ available = set(self._instances.keys())
188
+ bridge = self._get_bridge()
189
+ if bridge:
190
+ # Get from bridge's list_available if it has one
191
+ if hasattr(bridge, 'list_available'):
192
+ try:
193
+ available.update(bridge.list_available())
194
+ except:
195
+ pass
196
+ # Also check bridge's _instances directly
197
+ if hasattr(bridge, '_instances'):
198
+ available.update(bridge._instances.keys())
199
+ # For C++, also list module exports
200
+ if self.language == SupportedLanguage.CPP and hasattr(bridge, '_modules'):
201
+ for mod in bridge._modules.values():
202
+ for attr in dir(mod):
203
+ if not attr.startswith('_'):
204
+ available.add(attr)
205
+ return sorted(available)
206
+
207
+ def remove_instance(self, name: str) -> bool:
208
+ """Remove a shared instance"""
209
+ if name in self._instances:
210
+ del self._instances[name]
211
+ return True
212
+ return False
213
+
214
+ def get_transformer(self) -> 'LanguageTransformer':
215
+ """Get the syntax transformer for this language"""
216
+ if self._transformer is None:
217
+ self._transformer = create_transformer(self)
218
+ return self._transformer
219
+
220
+ # === Runtime Bridge Methods (v4.1.1) ===
221
+
222
+ def load_module(self, module_name: str) -> Any:
223
+ """Load a module from the target language (C++ only)."""
224
+ bridge = self._get_bridge()
225
+ if bridge and hasattr(bridge, 'load_module'):
226
+ return bridge.load_module(module_name)
227
+ raise NotImplementedError(f"load_module not supported for {self.name}")
228
+
229
+ def create(self, class_name: str, *args) -> Any:
230
+ """Create an instance of a class in the target language."""
231
+ bridge = self._get_bridge()
232
+ if bridge and hasattr(bridge, 'create'):
233
+ return bridge.create(class_name, *args)
234
+ raise NotImplementedError(f"create not supported for {self.name}")
235
+
236
+ def load_class(self, class_name: str) -> Any:
237
+ """Load a class from the target language (Java only)."""
238
+ bridge = self._get_bridge()
239
+ if bridge and hasattr(bridge, 'load_class'):
240
+ return bridge.load_class(class_name)
241
+ raise NotImplementedError(f"load_class not supported for {self.name}")
242
+
243
+ def add_classpath(self, path: str) -> None:
244
+ """Add to classpath (Java only)."""
245
+ bridge = self._get_bridge()
246
+ if bridge and hasattr(bridge, 'add_classpath'):
247
+ bridge.add_classpath(path)
248
+ else:
249
+ raise NotImplementedError(f"add_classpath not supported for {self.name}")
250
+
251
+ def eval(self, code: str) -> Any:
252
+ """Evaluate code in the target language (JavaScript only)."""
253
+ bridge = self._get_bridge()
254
+ if bridge and hasattr(bridge, 'eval'):
255
+ return bridge.eval(code)
256
+ raise NotImplementedError(f"eval not supported for {self.name}")
257
+
258
+ def call(self, func_name: str, *args) -> Any:
259
+ """Call a function in the target language (JavaScript only)."""
260
+ bridge = self._get_bridge()
261
+ if bridge and hasattr(bridge, 'call'):
262
+ return bridge.call(func_name, *args)
263
+ raise NotImplementedError(f"call not supported for {self.name}")
264
+
265
+ def is_available(self) -> bool:
266
+ """Check if the runtime for this language is available."""
267
+ bridge = self._get_bridge()
268
+ if bridge:
269
+ return bridge.is_available()
270
+ return True # Python/C# don't need external runtimes
271
+
272
+ def __getattr__(self, name: str) -> Any:
273
+ """Allow method-like access for convenience"""
274
+ if name == 'get':
275
+ return self.get_instance
276
+ raise AttributeError(f"'{type(self).__name__}' has no attribute '{name}'")
277
+
278
+
279
+ class LanguageTransformer:
280
+ """
281
+ Base class for transforming language-specific syntax to CSSL.
282
+
283
+ Each language has a specific transformer that handles its unique syntax.
284
+ """
285
+
286
+ def __init__(self, lang_support: LanguageSupport):
287
+ self.lang = lang_support
288
+ self.syntax = lang_support.syntax
289
+
290
+ def transform_source(self, source: str) -> str:
291
+ """Transform source code from target language to CSSL"""
292
+ raise NotImplementedError("Subclasses must implement transform_source")
293
+
294
+ def _common_replacements(self, stmt: str) -> str:
295
+ """Apply common replacements across all languages"""
296
+ return stmt
297
+
298
+
299
+ class PythonTransformer(LanguageTransformer):
300
+ """
301
+ Transforms Python syntax to CSSL.
302
+
303
+ Handles:
304
+ - Indentation-based blocks -> brace-based blocks
305
+ - def -> define
306
+ - print() -> printl()
307
+ - self. -> this->
308
+ - None -> null
309
+ - Python-style for loops -> CSSL for loops
310
+ """
311
+
312
+ def transform_source(self, source: str) -> str:
313
+ lines = source.split('\n')
314
+ result = []
315
+ indent_stack = [0] # Stack of indentation levels
316
+
317
+ for i, line in enumerate(lines):
318
+ stripped = line.lstrip()
319
+
320
+ # Handle empty lines and comments
321
+ if not stripped:
322
+ continue
323
+ if stripped.startswith('#'):
324
+ # Convert Python comment to CSSL comment
325
+ result.append('// ' + stripped[1:].lstrip())
326
+ continue
327
+
328
+ current_indent = len(line) - len(stripped)
329
+
330
+ # Handle dedent - close blocks
331
+ while len(indent_stack) > 1 and current_indent < indent_stack[-1]:
332
+ indent_stack.pop()
333
+ result.append(' ' * indent_stack[-1] + '}')
334
+
335
+ # Transform the statement
336
+ transformed = self._transform_statement(stripped)
337
+
338
+ # Check if line opens a new block (ends with :)
339
+ if stripped.rstrip().endswith(':'):
340
+ # Remove trailing colon, add opening brace
341
+ transformed = transformed.rstrip(':').rstrip() + ' {'
342
+ # Get next line's indentation
343
+ next_indent = self._get_next_indent(lines, i)
344
+ if next_indent > current_indent:
345
+ indent_stack.append(next_indent)
346
+ elif not transformed.endswith(('{', '}', ';')):
347
+ # Add semicolon if not a block statement
348
+ transformed += ';'
349
+
350
+ result.append(' ' * current_indent + transformed)
351
+
352
+ # Close remaining open blocks
353
+ while len(indent_stack) > 1:
354
+ indent_stack.pop()
355
+ result.append(' ' * indent_stack[-1] + '}')
356
+
357
+ return '\n'.join(result)
358
+
359
+ def _transform_statement(self, stmt: str) -> str:
360
+ """Transform a single Python statement to CSSL"""
361
+
362
+ # def func(args): -> define func(args)
363
+ # Handles: def func(self, param: type = default) -> ReturnType:
364
+ if stmt.startswith('def '):
365
+ # Match function with optional return type annotation
366
+ match = re.match(r'def\s+(\w+)\s*\((.*?)\)(?:\s*->\s*\w+)?\s*:', stmt)
367
+ if match:
368
+ func_name = match.group(1)
369
+ params = match.group(2)
370
+ # Strip type annotations from parameters
371
+ params = self._strip_type_annotations(params)
372
+ # Remove 'self' parameter (first param in methods)
373
+ params = self._strip_self_param(params)
374
+ return f"define {func_name}({params})"
375
+
376
+ # class ClassName(Parent): -> class ClassName : extends Parent
377
+ if stmt.startswith('class '):
378
+ match = re.match(r'class\s+(\w+)(?:\s*\((.*?)\))?\s*:', stmt)
379
+ if match:
380
+ class_name = match.group(1)
381
+ parent = match.group(2)
382
+ if parent and parent.strip():
383
+ return f"class {class_name} : extends {parent}"
384
+ return f"class {class_name}"
385
+
386
+ # if condition: -> if (condition)
387
+ if stmt.startswith('if '):
388
+ match = re.match(r'if\s+(.+?):', stmt)
389
+ if match:
390
+ condition = match.group(1)
391
+ return f"if ({condition})"
392
+
393
+ # elif condition: -> elif (condition)
394
+ if stmt.startswith('elif '):
395
+ match = re.match(r'elif\s+(.+?):', stmt)
396
+ if match:
397
+ condition = match.group(1)
398
+ return f"elif ({condition})"
399
+
400
+ # else: -> else
401
+ if stmt.strip() == 'else:':
402
+ return 'else'
403
+
404
+ # while condition: -> while (condition)
405
+ if stmt.startswith('while '):
406
+ match = re.match(r'while\s+(.+?):', stmt)
407
+ if match:
408
+ condition = match.group(1)
409
+ return f"while ({condition})"
410
+
411
+ # for i in range(n): -> for (i in range(0, n))
412
+ # for i in iterable: -> for (i in iterable)
413
+ if stmt.startswith('for '):
414
+ match = re.match(r'for\s+(\w+)\s+in\s+(.+?):', stmt)
415
+ if match:
416
+ var = match.group(1)
417
+ iterable = match.group(2)
418
+ # Handle range with single argument
419
+ range_match = re.match(r'range\s*\(\s*(\d+)\s*\)', iterable)
420
+ if range_match:
421
+ return f"for ({var} in range(0, {range_match.group(1)}))"
422
+ return f"for ({var} in {iterable})"
423
+
424
+ # try: -> try
425
+ if stmt.strip() == 'try:':
426
+ return 'try'
427
+
428
+ # except Exception as e: -> catch (e)
429
+ if stmt.startswith('except'):
430
+ match = re.match(r'except\s*(?:\w+\s+)?(?:as\s+(\w+))?\s*:', stmt)
431
+ if match:
432
+ var = match.group(1) or 'e'
433
+ return f"catch ({var})"
434
+
435
+ # finally: -> finally
436
+ if stmt.strip() == 'finally:':
437
+ return 'finally'
438
+
439
+ # return value -> return value
440
+ # (no change needed, just ensure semicolon is added)
441
+
442
+ # Common replacements
443
+ stmt = self._apply_replacements(stmt)
444
+
445
+ return stmt
446
+
447
+ def _apply_replacements(self, stmt: str) -> str:
448
+ """Apply common Python to CSSL replacements"""
449
+ # print() -> printl()
450
+ stmt = re.sub(r'\bprint\s*\(', 'printl(', stmt)
451
+
452
+ # self. -> this->
453
+ stmt = stmt.replace('self.', 'this->')
454
+
455
+ # None -> null
456
+ stmt = re.sub(r'\bNone\b', 'null', stmt)
457
+
458
+ # True/False stay the same (CSSL supports both cases)
459
+
460
+ # v4.2.0: Transform compound assignment operators (CSSL doesn't have +=, -=, etc.)
461
+ # var -= expr -> var = var - expr
462
+ # var += expr -> var = var + expr
463
+ # var *= expr -> var = var * expr
464
+ # var /= expr -> var = var / expr
465
+ # Handles: this->health -= damage, x += 1, etc.
466
+ compound_ops = [
467
+ (r'(\S+)\s*-=\s*(.+)', r'\1 = \1 - \2'), # -= to = -
468
+ (r'(\S+)\s*\+=\s*(.+)', r'\1 = \1 + \2'), # += to = +
469
+ (r'(\S+)\s*\*=\s*(.+)', r'\1 = \1 * \2'), # *= to = *
470
+ (r'(\S+)\s*/=\s*(.+)', r'\1 = \1 / \2'), # /= to = /
471
+ ]
472
+ for pattern, replacement in compound_ops:
473
+ stmt = re.sub(pattern, replacement, stmt)
474
+
475
+ # __init__ -> constructor handling would be done at class level
476
+
477
+ return stmt
478
+
479
+ def _get_next_indent(self, lines: List[str], current_idx: int) -> int:
480
+ """Get indentation of next non-empty, non-comment line"""
481
+ for i in range(current_idx + 1, len(lines)):
482
+ line = lines[i]
483
+ stripped = line.lstrip()
484
+ if stripped and not stripped.startswith('#'):
485
+ return len(line) - len(stripped)
486
+ return 0
487
+
488
+ def _strip_type_annotations(self, params: str) -> str:
489
+ """Strip Python type annotations from parameter list.
490
+
491
+ Examples:
492
+ 'self, x: int, y: str = "default"' -> 'self, x, y = "default"'
493
+ 'a: List[int], b: Dict[str, int]' -> 'a, b'
494
+ """
495
+ if not params.strip():
496
+ return params
497
+
498
+ result = []
499
+ # Split by comma, but be careful with nested brackets
500
+ depth = 0
501
+ current = []
502
+ for char in params + ',':
503
+ if char in '([{':
504
+ depth += 1
505
+ current.append(char)
506
+ elif char in ')]}':
507
+ depth -= 1
508
+ current.append(char)
509
+ elif char == ',' and depth == 0:
510
+ param = ''.join(current).strip()
511
+ if param:
512
+ # Strip type annotation: "name: type = default" -> "name = default"
513
+ # or "name: type" -> "name"
514
+ colon_match = re.match(r'^(\w+)\s*:', param)
515
+ if colon_match:
516
+ param_name = colon_match.group(1)
517
+ # Check for default value after type annotation
518
+ default_match = re.search(r'=\s*(.+)$', param)
519
+ if default_match:
520
+ param = f"{param_name} = {default_match.group(1)}"
521
+ else:
522
+ param = param_name
523
+ result.append(param)
524
+ current = []
525
+ else:
526
+ current.append(char)
527
+
528
+ return ', '.join(result)
529
+
530
+ def _strip_self_param(self, params: str) -> str:
531
+ """Remove 'self' parameter from method parameters.
532
+
533
+ Examples:
534
+ 'self, x, y' -> 'x, y'
535
+ 'self' -> ''
536
+ 'x, y' -> 'x, y'
537
+ """
538
+ if not params.strip():
539
+ return params
540
+
541
+ parts = [p.strip() for p in params.split(',')]
542
+ if parts and parts[0] == 'self':
543
+ parts = parts[1:]
544
+ return ', '.join(parts)
545
+
546
+
547
+ class JavaScriptTransformer(LanguageTransformer):
548
+ """
549
+ Transforms JavaScript syntax to CSSL.
550
+
551
+ Handles:
552
+ - let/const/var -> dynamic
553
+ - function name() -> define name()
554
+ - console.log() -> printl()
555
+ - null/undefined -> null
556
+ - Arrow functions (basic support)
557
+ """
558
+
559
+ def transform_source(self, source: str) -> str:
560
+ lines = source.split('\n')
561
+ result = []
562
+
563
+ for line in lines:
564
+ stripped = line.strip()
565
+
566
+ # Skip empty lines
567
+ if not stripped:
568
+ continue
569
+
570
+ # Convert comments
571
+ if stripped.startswith('//'):
572
+ result.append(stripped)
573
+ continue
574
+
575
+ # Transform the line
576
+ transformed = self._transform_line(stripped)
577
+ result.append(transformed)
578
+
579
+ return '\n'.join(result)
580
+
581
+ def _transform_line(self, line: str) -> str:
582
+ """Transform a single JavaScript line to CSSL"""
583
+
584
+ # function name(args) { -> define name(args) {
585
+ match = re.match(r'function\s+(\w+)\s*\((.*?)\)\s*\{?', line)
586
+ if match:
587
+ func_name = match.group(1)
588
+ params = match.group(2)
589
+ suffix = ' {' if line.rstrip().endswith('{') else ''
590
+ return f"define {func_name}({params}){suffix}"
591
+
592
+ # const/let/var name = value; -> dynamic name = value;
593
+ match = re.match(r'(const|let|var)\s+(\w+)\s*=\s*(.+)', line)
594
+ if match:
595
+ var_name = match.group(2)
596
+ value = match.group(3)
597
+ return f"dynamic {var_name} = {value}"
598
+
599
+ # const/let/var name; -> dynamic name;
600
+ match = re.match(r'(const|let|var)\s+(\w+)\s*;', line)
601
+ if match:
602
+ var_name = match.group(2)
603
+ return f"dynamic {var_name};"
604
+
605
+ # class Name { or class Name extends Parent {
606
+ match = re.match(r'class\s+(\w+)(?:\s+extends\s+(\w+))?\s*\{?', line)
607
+ if match:
608
+ class_name = match.group(1)
609
+ parent = match.group(2)
610
+ suffix = ' {' if line.rstrip().endswith('{') else ''
611
+ if parent:
612
+ return f"class {class_name} : extends {parent}{suffix}"
613
+ return f"class {class_name}{suffix}"
614
+
615
+ # constructor(args) { -> constr ClassName(args) {
616
+ if line.strip().startswith('constructor'):
617
+ match = re.match(r'constructor\s*\((.*?)\)\s*\{?', line)
618
+ if match:
619
+ params = match.group(1)
620
+ suffix = ' {' if line.rstrip().endswith('{') else ''
621
+ return f"constr __init__({params}){suffix}"
622
+
623
+ # Common replacements
624
+ line = self._apply_replacements(line)
625
+
626
+ return line
627
+
628
+ def _apply_replacements(self, line: str) -> str:
629
+ """Apply common JavaScript to CSSL replacements"""
630
+ # console.log() -> printl()
631
+ line = re.sub(r'console\.log\s*\(', 'printl(', line)
632
+
633
+ # console.error() -> error()
634
+ line = re.sub(r'console\.error\s*\(', 'error(', line)
635
+
636
+ # console.warn() -> warn()
637
+ line = re.sub(r'console\.warn\s*\(', 'warn(', line)
638
+
639
+ # true/false -> True/False
640
+ line = re.sub(r'\btrue\b', 'True', line)
641
+ line = re.sub(r'\bfalse\b', 'False', line)
642
+
643
+ # undefined -> null
644
+ line = re.sub(r'\bundefined\b', 'null', line)
645
+
646
+ # this. stays as this. (CSSL uses this-> but also supports this.)
647
+
648
+ return line
649
+
650
+
651
+ class JavaTransformer(LanguageTransformer):
652
+ """
653
+ Transforms Java syntax to CSSL.
654
+
655
+ Handles:
656
+ - System.out.println() -> printl()
657
+ - true/false -> True/False
658
+ - String -> string (optional lowercase)
659
+ """
660
+
661
+ def transform_source(self, source: str) -> str:
662
+ lines = source.split('\n')
663
+ result = []
664
+
665
+ for line in lines:
666
+ stripped = line.strip()
667
+
668
+ if not stripped:
669
+ continue
670
+
671
+ if stripped.startswith('//'):
672
+ result.append(stripped)
673
+ continue
674
+
675
+ transformed = self._transform_line(stripped)
676
+ result.append(transformed)
677
+
678
+ return '\n'.join(result)
679
+
680
+ def _transform_line(self, line: str) -> str:
681
+ """Transform a single Java line to CSSL"""
682
+
683
+ # public/private/protected static void main(String[] args)
684
+ # -> define main(args)
685
+ match = re.match(r'(?:public|private|protected)?\s*(?:static)?\s*(?:void|int|String|boolean|float|double)\s+(\w+)\s*\((.*?)\)\s*\{?', line)
686
+ if match:
687
+ func_name = match.group(1)
688
+ params = match.group(2)
689
+ # Simplify Java params: String[] args -> args
690
+ params = re.sub(r'\w+(?:\[\])?\s+(\w+)', r'\1', params)
691
+ suffix = ' {' if line.rstrip().endswith('{') else ''
692
+ return f"define {func_name}({params}){suffix}"
693
+
694
+ # class Name extends Parent implements Interface {
695
+ match = re.match(r'(?:public\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+\w+(?:,\s*\w+)*)?\s*\{?', line)
696
+ if match:
697
+ class_name = match.group(1)
698
+ parent = match.group(2)
699
+ suffix = ' {' if line.rstrip().endswith('{') else ''
700
+ if parent:
701
+ return f"class {class_name} : extends {parent}{suffix}"
702
+ return f"class {class_name}{suffix}"
703
+
704
+ # Common replacements
705
+ line = self._apply_replacements(line)
706
+
707
+ return line
708
+
709
+ def _apply_replacements(self, line: str) -> str:
710
+ """Apply common Java to CSSL replacements"""
711
+ # System.out.println() -> printl()
712
+ line = re.sub(r'System\.out\.println\s*\(', 'printl(', line)
713
+ line = re.sub(r'System\.out\.print\s*\(', 'print(', line)
714
+
715
+ # true/false -> True/False
716
+ line = re.sub(r'\btrue\b', 'True', line)
717
+ line = re.sub(r'\bfalse\b', 'False', line)
718
+
719
+ # String -> string (CSSL convention)
720
+ line = re.sub(r'\bString\b', 'string', line)
721
+
722
+ return line
723
+
724
+
725
+ class CSharpTransformer(LanguageTransformer):
726
+ """
727
+ Transforms C# syntax to CSSL.
728
+
729
+ Handles:
730
+ - Console.WriteLine() -> printl()
731
+ - true/false -> True/False
732
+ - var -> dynamic
733
+ """
734
+
735
+ def transform_source(self, source: str) -> str:
736
+ lines = source.split('\n')
737
+ result = []
738
+
739
+ for line in lines:
740
+ stripped = line.strip()
741
+
742
+ if not stripped:
743
+ continue
744
+
745
+ if stripped.startswith('//'):
746
+ result.append(stripped)
747
+ continue
748
+
749
+ transformed = self._transform_line(stripped)
750
+ result.append(transformed)
751
+
752
+ return '\n'.join(result)
753
+
754
+ def _transform_line(self, line: str) -> str:
755
+ """Transform a single C# line to CSSL"""
756
+
757
+ # public/private void MethodName(params) {
758
+ match = re.match(r'(?:public|private|protected|internal)?\s*(?:static)?\s*(?:async)?\s*(?:void|int|string|bool|float|double|var|dynamic|\w+)\s+(\w+)\s*\((.*?)\)\s*\{?', line)
759
+ if match and not line.strip().startswith('class'):
760
+ func_name = match.group(1)
761
+ params = match.group(2)
762
+ # Simplify C# params: string name -> name
763
+ params = re.sub(r'\w+\s+(\w+)', r'\1', params)
764
+ suffix = ' {' if line.rstrip().endswith('{') else ''
765
+ return f"define {func_name}({params}){suffix}"
766
+
767
+ # class Name : Parent {
768
+ match = re.match(r'(?:public\s+)?(?:partial\s+)?class\s+(\w+)(?:\s*:\s*(\w+))?\s*\{?', line)
769
+ if match:
770
+ class_name = match.group(1)
771
+ parent = match.group(2)
772
+ suffix = ' {' if line.rstrip().endswith('{') else ''
773
+ if parent:
774
+ return f"class {class_name} : extends {parent}{suffix}"
775
+ return f"class {class_name}{suffix}"
776
+
777
+ # var name = value; -> dynamic name = value;
778
+ match = re.match(r'var\s+(\w+)\s*=\s*(.+)', line)
779
+ if match:
780
+ var_name = match.group(1)
781
+ value = match.group(2)
782
+ return f"dynamic {var_name} = {value}"
783
+
784
+ # Common replacements
785
+ line = self._apply_replacements(line)
786
+
787
+ return line
788
+
789
+ def _apply_replacements(self, line: str) -> str:
790
+ """Apply common C# to CSSL replacements"""
791
+ # Console.WriteLine() -> printl()
792
+ line = re.sub(r'Console\.WriteLine\s*\(', 'printl(', line)
793
+ line = re.sub(r'Console\.Write\s*\(', 'print(', line)
794
+
795
+ # true/false -> True/False
796
+ line = re.sub(r'\btrue\b', 'True', line)
797
+ line = re.sub(r'\bfalse\b', 'False', line)
798
+
799
+ return line
800
+
801
+
802
+ class CppTransformer(LanguageTransformer):
803
+ """
804
+ Transforms C++ syntax to CSSL.
805
+
806
+ Handles:
807
+ - std::cout << x << std::endl; -> printl(x);
808
+ - nullptr -> null
809
+ - auto -> dynamic
810
+ - true/false -> True/False
811
+ """
812
+
813
+ def transform_source(self, source: str) -> str:
814
+ lines = source.split('\n')
815
+ result = []
816
+
817
+ for line in lines:
818
+ stripped = line.strip()
819
+
820
+ if not stripped:
821
+ continue
822
+
823
+ if stripped.startswith('//'):
824
+ result.append(stripped)
825
+ continue
826
+
827
+ transformed = self._transform_line(stripped)
828
+ result.append(transformed)
829
+
830
+ return '\n'.join(result)
831
+
832
+ def _transform_line(self, line: str) -> str:
833
+ """Transform a single C++ line to CSSL"""
834
+
835
+ # void/int/etc functionName(params) {
836
+ match = re.match(r'(?:virtual\s+)?(?:static\s+)?(?:inline\s+)?(?:void|int|string|bool|float|double|auto|\w+)\s+(\w+)\s*\((.*?)\)\s*(?:const)?\s*(?:override)?\s*\{?', line)
837
+ if match and not any(kw in line for kw in ['class ', 'struct ', 'namespace ']):
838
+ func_name = match.group(1)
839
+ params = match.group(2)
840
+ # Simplify C++ params: const std::string& name -> name
841
+ params = re.sub(r'(?:const\s+)?(?:std::)?(?:\w+)(?:&|\*)?\s+(\w+)', r'\1', params)
842
+ suffix = ' {' if line.rstrip().endswith('{') else ''
843
+ return f"define {func_name}({params}){suffix}"
844
+
845
+ # class Name : public Parent {
846
+ match = re.match(r'class\s+(\w+)(?:\s*:\s*(?:public|protected|private)\s+(\w+))?\s*\{?', line)
847
+ if match:
848
+ class_name = match.group(1)
849
+ parent = match.group(2)
850
+ suffix = ' {' if line.rstrip().endswith('{') else ''
851
+ if parent:
852
+ return f"class {class_name} : extends {parent}{suffix}"
853
+ return f"class {class_name}{suffix}"
854
+
855
+ # auto name = value; -> dynamic name = value;
856
+ match = re.match(r'auto\s+(\w+)\s*=\s*(.+)', line)
857
+ if match:
858
+ var_name = match.group(1)
859
+ value = match.group(2)
860
+ return f"dynamic {var_name} = {value}"
861
+
862
+ # Common replacements
863
+ line = self._apply_replacements(line)
864
+
865
+ return line
866
+
867
+ def _apply_replacements(self, line: str) -> str:
868
+ """Apply common C++ to CSSL replacements"""
869
+ # std::cout << x << std::endl; -> printl(x);
870
+ match = re.match(r'std::cout\s*<<\s*(.*?)\s*<<\s*std::endl\s*;', line)
871
+ if match:
872
+ content = match.group(1)
873
+ return f'printl({content});'
874
+
875
+ match = re.match(r'std::cout\s*<<\s*(.*?)\s*;', line)
876
+ if match:
877
+ content = match.group(1)
878
+ return f'print({content});'
879
+
880
+ # true/false -> True/False
881
+ line = re.sub(r'\btrue\b', 'True', line)
882
+ line = re.sub(r'\bfalse\b', 'False', line)
883
+
884
+ # nullptr -> null
885
+ line = re.sub(r'\bnullptr\b', 'null', line)
886
+
887
+ # auto -> dynamic (for standalone declarations)
888
+ line = re.sub(r'\bauto\b', 'dynamic', line)
889
+
890
+ return line
891
+
892
+
893
+ # =============================================================================
894
+ # CROSS-LANGUAGE RUNTIME BRIDGES (v4.1.1)
895
+ # =============================================================================
896
+
897
+ class RuntimeBridge:
898
+ """
899
+ Base class for cross-language runtime bridges.
900
+
901
+ v4.1.1: Provides bidirectional instance sharing and access between
902
+ CSSL and target languages (C++, Java, JavaScript).
903
+ """
904
+
905
+ def __init__(self):
906
+ self._instances: Dict[str, Any] = {}
907
+ self._initialized = False
908
+
909
+ def initialize(self) -> bool:
910
+ """Initialize the runtime bridge. Returns True if successful."""
911
+ raise NotImplementedError
912
+
913
+ def is_available(self) -> bool:
914
+ """Check if this runtime is available on the system."""
915
+ raise NotImplementedError
916
+
917
+ def share(self, name: str, instance: Any) -> None:
918
+ """Share an instance for cross-language access."""
919
+ self._instances[name] = instance
920
+
921
+ def get_instance(self, name: str) -> Any:
922
+ """Get a shared instance by name."""
923
+ return self._instances.get(name)
924
+
925
+ def has_instance(self, name: str) -> bool:
926
+ """Check if an instance exists."""
927
+ return name in self._instances
928
+
929
+ def list_available(self) -> List[str]:
930
+ """List all available instances and classes."""
931
+ return sorted(self._instances.keys())
932
+
933
+ def call_method(self, instance: Any, method: str, *args) -> Any:
934
+ """Call a method on a foreign language object."""
935
+ raise NotImplementedError
936
+
937
+ def get_field(self, instance: Any, field: str) -> Any:
938
+ """Get a field value from a foreign language object."""
939
+ raise NotImplementedError
940
+
941
+ def set_field(self, instance: Any, field: str, value: Any) -> None:
942
+ """Set a field value on a foreign language object."""
943
+ raise NotImplementedError
944
+
945
+
946
+ class CppRuntimeBridge(RuntimeBridge):
947
+ """
948
+ C++ Runtime Bridge using IncludeCPP's pybind11 modules.
949
+
950
+ Accesses C++ classes and objects via the generated Python bindings.
951
+ v4.1.1: Full bidirectional support with automatic module discovery.
952
+
953
+ Usage in CSSL:
954
+ cpp = libinclude("c++");
955
+
956
+ // List available C++ classes/modules
957
+ printl(cpp.list_available());
958
+
959
+ // Access a C++ module built with IncludeCPP
960
+ cpp.load_module("mymodule");
961
+
962
+ // Create C++ instance
963
+ obj = cpp.create("MyClass", 10, 20);
964
+ cpp.share("MyInstance", obj);
965
+
966
+ // Access via $ syntax
967
+ instance = cpp$MyInstance;
968
+
969
+ // Direct class access (if module is loaded)
970
+ MyClass = cpp$MyClass;
971
+ obj2 = new MyClass(5, 10);
972
+ """
973
+
974
+ def __init__(self):
975
+ super().__init__()
976
+ self._modules: Dict[str, Any] = {}
977
+ self._api = None
978
+ self._class_cache: Dict[str, Any] = {} # Cache class lookups
979
+
980
+ def initialize(self) -> bool:
981
+ """Initialize by connecting to IncludeCPP's CppApi."""
982
+ if self._initialized:
983
+ return True
984
+ try:
985
+ from ...cpp_api import CppApi
986
+ self._api = CppApi()
987
+ self._initialized = True
988
+ # Auto-load all registered modules
989
+ for name in self._api.registry.keys():
990
+ try:
991
+ module = self._api.include(name)
992
+ self._modules[name] = module
993
+ # Cache all classes from the module
994
+ self._cache_module_classes(name, module)
995
+ except Exception:
996
+ pass # Module might not be built yet
997
+ return True
998
+ except Exception as e:
999
+ # CppApi not available, but bridge still works for sharing
1000
+ self._initialized = True
1001
+ return True
1002
+
1003
+ def _cache_module_classes(self, module_name: str, module: Any) -> None:
1004
+ """Cache all classes and functions from a module for quick access."""
1005
+ for attr_name in dir(module):
1006
+ if not attr_name.startswith('_'):
1007
+ attr = getattr(module, attr_name, None)
1008
+ if attr is not None:
1009
+ self._class_cache[attr_name] = attr
1010
+
1011
+ def is_available(self) -> bool:
1012
+ """C++ is always available via pybind11."""
1013
+ return True
1014
+
1015
+ def load_module(self, module_name: str) -> Any:
1016
+ """Load a C++ module built with IncludeCPP."""
1017
+ if not self._initialized:
1018
+ self.initialize()
1019
+
1020
+ # Check if already loaded
1021
+ if module_name in self._modules:
1022
+ return self._modules[module_name]
1023
+
1024
+ if self._api and module_name in self._api.registry:
1025
+ module = self._api.include(module_name)
1026
+ self._modules[module_name] = module
1027
+ self._cache_module_classes(module_name, module)
1028
+ return module
1029
+
1030
+ # Try to import as a regular Python module (for external pybind11 modules)
1031
+ try:
1032
+ import importlib
1033
+ module = importlib.import_module(module_name)
1034
+ self._modules[module_name] = module
1035
+ self._cache_module_classes(module_name, module)
1036
+ return module
1037
+ except ImportError:
1038
+ pass
1039
+
1040
+ return None
1041
+
1042
+ def get_class(self, class_name: str) -> Any:
1043
+ """Get a C++ class by name (from any loaded module)."""
1044
+ if not self._initialized:
1045
+ self.initialize()
1046
+
1047
+ # Check cache first
1048
+ if class_name in self._class_cache:
1049
+ return self._class_cache[class_name]
1050
+
1051
+ # Search through modules
1052
+ for mod in self._modules.values():
1053
+ if hasattr(mod, class_name):
1054
+ cls = getattr(mod, class_name)
1055
+ self._class_cache[class_name] = cls
1056
+ return cls
1057
+
1058
+ return None
1059
+
1060
+ def create(self, class_name: str, *args, module: str = None) -> Any:
1061
+ """Create an instance of a C++ class."""
1062
+ if not self._initialized:
1063
+ self.initialize()
1064
+
1065
+ # Try cache first
1066
+ if class_name in self._class_cache:
1067
+ return self._class_cache[class_name](*args)
1068
+
1069
+ # Search through loaded modules for the class
1070
+ for mod_name, mod in self._modules.items():
1071
+ if module and mod_name != module:
1072
+ continue
1073
+ if hasattr(mod, class_name):
1074
+ cls = getattr(mod, class_name)
1075
+ self._class_cache[class_name] = cls
1076
+ return cls(*args)
1077
+
1078
+ raise ValueError(f"C++ class '{class_name}' not found. Available: {self.list_available()}")
1079
+
1080
+ def get_instance(self, name: str) -> Any:
1081
+ """Get a shared instance OR a class by name."""
1082
+ # First check shared instances
1083
+ instance = self._instances.get(name)
1084
+ if instance is not None:
1085
+ return instance
1086
+
1087
+ # Then check class cache
1088
+ if name in self._class_cache:
1089
+ return self._class_cache[name]
1090
+
1091
+ # Finally search modules
1092
+ for mod in self._modules.values():
1093
+ if hasattr(mod, name):
1094
+ attr = getattr(mod, name)
1095
+ self._class_cache[name] = attr
1096
+ return attr
1097
+
1098
+ return None
1099
+
1100
+ def list_available(self) -> List[str]:
1101
+ """List all available C++ classes, functions, and shared instances."""
1102
+ if not self._initialized:
1103
+ self.initialize()
1104
+
1105
+ available = set()
1106
+
1107
+ # Add shared instances
1108
+ available.update(self._instances.keys())
1109
+
1110
+ # Add cached classes
1111
+ available.update(self._class_cache.keys())
1112
+
1113
+ # Add module exports
1114
+ for mod in self._modules.values():
1115
+ for attr in dir(mod):
1116
+ if not attr.startswith('_'):
1117
+ available.add(attr)
1118
+
1119
+ return sorted(available)
1120
+
1121
+ def list_modules(self) -> List[str]:
1122
+ """List all loaded C++ module names."""
1123
+ if not self._initialized:
1124
+ self.initialize()
1125
+ return list(self._modules.keys())
1126
+
1127
+ def call_method(self, instance: Any, method: str, *args) -> Any:
1128
+ """Call a method on a C++ object."""
1129
+ if hasattr(instance, method):
1130
+ return getattr(instance, method)(*args)
1131
+ raise AttributeError(f"C++ object has no method '{method}'")
1132
+
1133
+ def get_field(self, instance: Any, field: str) -> Any:
1134
+ """Get a field from a C++ object."""
1135
+ return getattr(instance, field)
1136
+
1137
+ def set_field(self, instance: Any, field: str, value: Any) -> None:
1138
+ """Set a field on a C++ object."""
1139
+ setattr(instance, field, value)
1140
+
1141
+
1142
+ class JavaRuntimeBridge(RuntimeBridge):
1143
+ """
1144
+ Java Runtime Bridge using JPype.
1145
+
1146
+ Connects to JVM and allows access to Java classes and objects.
1147
+ v4.1.1: Full bidirectional support with class caching.
1148
+
1149
+ Requirements:
1150
+ pip install jpype1
1151
+
1152
+ Usage in CSSL:
1153
+ java = libinclude("java");
1154
+
1155
+ // Add JAR to classpath BEFORE first use
1156
+ java.add_classpath("/path/to/mylib.jar");
1157
+
1158
+ // Load a Java class
1159
+ MyClass = java.load_class("com.example.MyClass");
1160
+
1161
+ // Create instance
1162
+ obj = java.create("com.example.MyClass", 10, "hello");
1163
+ java.share("MyService", obj);
1164
+
1165
+ // Access via $ syntax
1166
+ service = java$MyService;
1167
+
1168
+ // List what's available
1169
+ printl(java.list_available());
1170
+ """
1171
+
1172
+ def __init__(self):
1173
+ super().__init__()
1174
+ self._jpype = None
1175
+ self._jvm_started = False
1176
+ self._classpaths: List[str] = []
1177
+ self._loaded_classes: Dict[str, Any] = {} # Cache loaded classes
1178
+
1179
+ def initialize(self) -> bool:
1180
+ """Initialize JPype and start JVM if not already running."""
1181
+ if self._initialized:
1182
+ return True
1183
+ try:
1184
+ import jpype
1185
+ import jpype.imports
1186
+ self._jpype = jpype
1187
+
1188
+ if not jpype.isJVMStarted():
1189
+ # Build classpath from all added paths
1190
+ import os
1191
+ sep = ";" if os.name == 'nt' else ":"
1192
+ classpath = sep.join(self._classpaths) if self._classpaths else None
1193
+ jpype.startJVM(classpath=classpath)
1194
+ self._jvm_started = True
1195
+
1196
+ self._initialized = True
1197
+ return True
1198
+ except ImportError:
1199
+ # JPype not installed
1200
+ self._initialized = True # Mark as initialized but limited
1201
+ return False
1202
+ except Exception as e:
1203
+ self._initialized = True
1204
+ return False
1205
+
1206
+ def is_available(self) -> bool:
1207
+ """Check if JPype is installed."""
1208
+ try:
1209
+ import jpype
1210
+ return True
1211
+ except ImportError:
1212
+ return False
1213
+
1214
+ def add_classpath(self, path: str) -> None:
1215
+ """Add a JAR or directory to the classpath (must be called before first use)."""
1216
+ import os
1217
+ # Normalize path for current OS
1218
+ path = os.path.abspath(path)
1219
+ if path not in self._classpaths:
1220
+ self._classpaths.append(path)
1221
+
1222
+ def load_class(self, class_name: str) -> Any:
1223
+ """Load a Java class by fully qualified name."""
1224
+ if not self._initialized:
1225
+ self.initialize()
1226
+ if not self._jpype:
1227
+ raise RuntimeError("JPype not available. Install with: pip install jpype1")
1228
+
1229
+ # Check cache
1230
+ if class_name in self._loaded_classes:
1231
+ return self._loaded_classes[class_name]
1232
+
1233
+ # Load the Java class
1234
+ try:
1235
+ cls = self._jpype.JClass(class_name)
1236
+ self._loaded_classes[class_name] = cls
1237
+ # Also cache by simple name
1238
+ simple_name = class_name.rsplit('.', 1)[-1]
1239
+ self._loaded_classes[simple_name] = cls
1240
+ return cls
1241
+ except Exception as e:
1242
+ raise RuntimeError(f"Failed to load Java class '{class_name}': {e}")
1243
+
1244
+ def create(self, class_name: str, *args) -> Any:
1245
+ """Create an instance of a Java class."""
1246
+ cls = self.load_class(class_name)
1247
+ return cls(*args)
1248
+
1249
+ def get_instance(self, name: str) -> Any:
1250
+ """Get a shared instance OR a loaded class by name."""
1251
+ # First check shared instances
1252
+ if name in self._instances:
1253
+ return self._instances[name]
1254
+ # Then check loaded classes (by simple name)
1255
+ if name in self._loaded_classes:
1256
+ return self._loaded_classes[name]
1257
+ return None
1258
+
1259
+ def list_available(self) -> List[str]:
1260
+ """List all available Java classes and shared instances."""
1261
+ available = set()
1262
+ available.update(self._instances.keys())
1263
+ # Add loaded classes (simple names only for readability)
1264
+ for name in self._loaded_classes.keys():
1265
+ if '.' not in name: # Only simple names
1266
+ available.add(name)
1267
+ return sorted(available)
1268
+
1269
+ def list_classpaths(self) -> List[str]:
1270
+ """List all added classpaths."""
1271
+ return list(self._classpaths)
1272
+
1273
+ def call_method(self, instance: Any, method: str, *args) -> Any:
1274
+ """Call a method on a Java object."""
1275
+ return getattr(instance, method)(*args)
1276
+
1277
+ def get_field(self, instance: Any, field: str) -> Any:
1278
+ """Get a field from a Java object."""
1279
+ return getattr(instance, field)
1280
+
1281
+ def set_field(self, instance: Any, field: str, value: Any) -> None:
1282
+ """Set a field on a Java object."""
1283
+ setattr(instance, field, value)
1284
+
1285
+ def call_static(self, class_name: str, method: str, *args) -> Any:
1286
+ """Call a static method on a Java class."""
1287
+ cls = self.load_class(class_name)
1288
+ return getattr(cls, method)(*args)
1289
+
1290
+ def shutdown(self) -> None:
1291
+ """Shutdown the JVM (only if we started it)."""
1292
+ if self._jvm_started and self._jpype and self._jpype.isJVMStarted():
1293
+ self._jpype.shutdownJVM()
1294
+ self._jvm_started = False
1295
+
1296
+
1297
+ class JavaScriptRuntimeBridge(RuntimeBridge):
1298
+ """
1299
+ JavaScript Runtime Bridge using Node.js subprocess.
1300
+
1301
+ Runs JavaScript code via Node.js and communicates via JSON IPC.
1302
+ v4.1.1: Full bidirectional support with persistent JS context.
1303
+
1304
+ Requirements:
1305
+ Node.js must be installed and in PATH
1306
+
1307
+ Usage in CSSL:
1308
+ js = libinclude("javascript");
1309
+
1310
+ // Execute JavaScript code
1311
+ result = js.eval("2 + 2");
1312
+
1313
+ // Define a function in JS context
1314
+ js.eval('''
1315
+ function greet(name) {
1316
+ return "Hello, " + name + "!";
1317
+ }
1318
+ ''');
1319
+
1320
+ // Call it
1321
+ result = js.call("greet", "World");
1322
+
1323
+ // Store value in JS context for $ access
1324
+ js.set("myValue", 42);
1325
+
1326
+ // Access via $ syntax
1327
+ value = js$myValue;
1328
+
1329
+ // List what's available
1330
+ printl(js.list_available());
1331
+ """
1332
+
1333
+ def __init__(self):
1334
+ super().__init__()
1335
+ self._process = None
1336
+ self._node_path = "node"
1337
+ self._js_context_vars: List[str] = [] # Track defined variables/functions
1338
+
1339
+ def initialize(self) -> bool:
1340
+ """Start Node.js subprocess if not already running."""
1341
+ if self._initialized:
1342
+ return True
1343
+ try:
1344
+ import subprocess
1345
+ import json
1346
+
1347
+ # Check if Node.js is available
1348
+ result = subprocess.run([self._node_path, "--version"],
1349
+ capture_output=True, text=True,
1350
+ timeout=5)
1351
+ if result.returncode != 0:
1352
+ self._initialized = True
1353
+ return False
1354
+
1355
+ # Start persistent Node.js process with IPC
1356
+ self._process = subprocess.Popen(
1357
+ [self._node_path, "-e", self._get_ipc_server_code()],
1358
+ stdin=subprocess.PIPE,
1359
+ stdout=subprocess.PIPE,
1360
+ stderr=subprocess.PIPE,
1361
+ text=True,
1362
+ bufsize=1
1363
+ )
1364
+
1365
+ self._initialized = True
1366
+ return True
1367
+ except Exception as e:
1368
+ self._initialized = True
1369
+ return False
1370
+
1371
+ def _get_ipc_server_code(self) -> str:
1372
+ """Get the Node.js IPC server code."""
1373
+ return '''
1374
+ const readline = require('readline');
1375
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false });
1376
+
1377
+ // Global context for storing variables accessible via $
1378
+ const __cssl_context = {};
1379
+
1380
+ rl.on('line', (line) => {
1381
+ try {
1382
+ const cmd = JSON.parse(line);
1383
+ let result;
1384
+
1385
+ if (cmd.type === 'eval') {
1386
+ result = eval(cmd.code);
1387
+ } else if (cmd.type === 'call') {
1388
+ const fn = eval(cmd.func);
1389
+ result = fn(...(cmd.args || []));
1390
+ } else if (cmd.type === 'get') {
1391
+ // First check context, then global
1392
+ result = __cssl_context[cmd.name] !== undefined
1393
+ ? __cssl_context[cmd.name]
1394
+ : (typeof global[cmd.name] !== 'undefined' ? global[cmd.name] : null);
1395
+ } else if (cmd.type === 'set') {
1396
+ __cssl_context[cmd.name] = cmd.value;
1397
+ global[cmd.name] = cmd.value;
1398
+ result = true;
1399
+ } else if (cmd.type === 'has') {
1400
+ result = cmd.name in __cssl_context || typeof global[cmd.name] !== 'undefined';
1401
+ } else if (cmd.type === 'list') {
1402
+ result = Object.keys(__cssl_context);
1403
+ } else if (cmd.type === 'define') {
1404
+ // Define a function that can be called later
1405
+ eval(cmd.code);
1406
+ if (cmd.name) {
1407
+ __cssl_context[cmd.name] = eval(cmd.name);
1408
+ }
1409
+ result = true;
1410
+ }
1411
+
1412
+ console.log(JSON.stringify({success: true, result: result}));
1413
+ } catch (e) {
1414
+ console.log(JSON.stringify({success: false, error: e.message}));
1415
+ }
1416
+ });
1417
+ '''
1418
+
1419
+ def is_available(self) -> bool:
1420
+ """Check if Node.js is available."""
1421
+ try:
1422
+ import subprocess
1423
+ result = subprocess.run([self._node_path, "--version"],
1424
+ capture_output=True, text=True,
1425
+ timeout=5)
1426
+ return result.returncode == 0
1427
+ except:
1428
+ return False
1429
+
1430
+ def eval(self, code: str) -> Any:
1431
+ """Evaluate JavaScript code and return the result."""
1432
+ return self._send_command({"type": "eval", "code": code})
1433
+
1434
+ def call(self, func_name: str, *args) -> Any:
1435
+ """Call a JavaScript function."""
1436
+ return self._send_command({"type": "call", "func": func_name, "args": list(args)})
1437
+
1438
+ def set(self, name: str, value: Any) -> None:
1439
+ """Set a variable in the JS context for $ access."""
1440
+ self._send_command({"type": "set", "name": name, "value": value})
1441
+ self._js_context_vars.append(name)
1442
+ # Also store locally for Python-side access
1443
+ self._instances[name] = value
1444
+
1445
+ def get(self, name: str) -> Any:
1446
+ """Get a variable from the JS context."""
1447
+ return self._send_command({"type": "get", "name": name})
1448
+
1449
+ def define(self, name: str, code: str) -> None:
1450
+ """Define a function or class in the JS context."""
1451
+ self._send_command({"type": "define", "name": name, "code": code})
1452
+ self._js_context_vars.append(name)
1453
+
1454
+ def get_instance(self, name: str) -> Any:
1455
+ """Get a shared instance from local cache or JS context."""
1456
+ # First check local Python instances
1457
+ if name in self._instances:
1458
+ return self._instances[name]
1459
+
1460
+ # Then try to get from JS context
1461
+ try:
1462
+ has_it = self._send_command({"type": "has", "name": name})
1463
+ if has_it:
1464
+ result = self._send_command({"type": "get", "name": name})
1465
+ if result is not None:
1466
+ self._instances[name] = result # Cache it
1467
+ return result
1468
+ except:
1469
+ pass
1470
+
1471
+ return None
1472
+
1473
+ def list_available(self) -> List[str]:
1474
+ """List all available variables in JS context and local instances."""
1475
+ available = set(self._instances.keys())
1476
+ available.update(self._js_context_vars)
1477
+
1478
+ # Also get from JS context
1479
+ try:
1480
+ js_vars = self._send_command({"type": "list"})
1481
+ if js_vars:
1482
+ available.update(js_vars)
1483
+ except:
1484
+ pass
1485
+
1486
+ return sorted(available)
1487
+
1488
+ def _send_command(self, cmd: dict) -> Any:
1489
+ """Send a command to Node.js and get the result."""
1490
+ if not self._initialized:
1491
+ self.initialize()
1492
+ if not self._process:
1493
+ raise RuntimeError("Node.js not available. Make sure Node.js is installed and in PATH.")
1494
+
1495
+ import json
1496
+
1497
+ try:
1498
+ self._process.stdin.write(json.dumps(cmd) + "\n")
1499
+ self._process.stdin.flush()
1500
+
1501
+ response_line = self._process.stdout.readline()
1502
+ if not response_line:
1503
+ raise RuntimeError("No response from Node.js process")
1504
+
1505
+ response = json.loads(response_line)
1506
+
1507
+ if response.get("success"):
1508
+ return response.get("result")
1509
+ else:
1510
+ raise RuntimeError(f"JavaScript error: {response.get('error')}")
1511
+ except json.JSONDecodeError as e:
1512
+ raise RuntimeError(f"Invalid JSON response from Node.js: {e}")
1513
+
1514
+ def call_method(self, instance: Any, method: str, *args) -> Any:
1515
+ """For JS objects stored locally, call method."""
1516
+ if hasattr(instance, method):
1517
+ return getattr(instance, method)(*args)
1518
+ # For remote JS objects, use eval
1519
+ raise NotImplementedError("Remote JS method calls not yet supported")
1520
+
1521
+ def get_field(self, instance: Any, field: str) -> Any:
1522
+ return getattr(instance, field, None)
1523
+
1524
+ def set_field(self, instance: Any, field: str, value: Any) -> None:
1525
+ setattr(instance, field, value)
1526
+
1527
+ def require(self, module_name: str) -> Any:
1528
+ """Require a Node.js module and return it."""
1529
+ return self.eval(f"require('{module_name}')")
1530
+
1531
+ def shutdown(self) -> None:
1532
+ """Shutdown the Node.js process."""
1533
+ if self._process:
1534
+ try:
1535
+ self._process.terminate()
1536
+ self._process.wait(timeout=2)
1537
+ except:
1538
+ self._process.kill()
1539
+ self._process = None
1540
+ self._initialized = False
1541
+
1542
+
1543
+ # Global bridge instances
1544
+ _cpp_bridge: Optional[CppRuntimeBridge] = None
1545
+ _java_bridge: Optional[JavaRuntimeBridge] = None
1546
+ _js_bridge: Optional[JavaScriptRuntimeBridge] = None
1547
+
1548
+
1549
+ def get_cpp_bridge() -> CppRuntimeBridge:
1550
+ """Get the global C++ runtime bridge."""
1551
+ global _cpp_bridge
1552
+ if _cpp_bridge is None:
1553
+ _cpp_bridge = CppRuntimeBridge()
1554
+ _cpp_bridge.initialize()
1555
+ return _cpp_bridge
1556
+
1557
+
1558
+ def get_java_bridge() -> JavaRuntimeBridge:
1559
+ """Get the global Java runtime bridge."""
1560
+ global _java_bridge
1561
+ if _java_bridge is None:
1562
+ _java_bridge = JavaRuntimeBridge()
1563
+ return _java_bridge
1564
+
1565
+
1566
+ def get_js_bridge() -> JavaScriptRuntimeBridge:
1567
+ """Get the global JavaScript runtime bridge."""
1568
+ global _js_bridge
1569
+ if _js_bridge is None:
1570
+ _js_bridge = JavaScriptRuntimeBridge()
1571
+ return _js_bridge
1572
+
1573
+
1574
+ # Language Registry
1575
+ LANGUAGE_DEFINITIONS: Dict[str, LanguageSupport] = {}
1576
+
1577
+
1578
+ def register_language(lang_id: str, lang_support: LanguageSupport) -> None:
1579
+ """Register a language definition"""
1580
+ LANGUAGE_DEFINITIONS[lang_id.lower()] = lang_support
1581
+
1582
+
1583
+ def get_language(lang_id: str) -> Optional[LanguageSupport]:
1584
+ """Get a language definition by ID"""
1585
+ return LANGUAGE_DEFINITIONS.get(lang_id.lower())
1586
+
1587
+
1588
+ def list_languages() -> List[str]:
1589
+ """List all registered language IDs"""
1590
+ return list(LANGUAGE_DEFINITIONS.keys())
1591
+
1592
+
1593
+ def create_transformer(lang_support: LanguageSupport) -> LanguageTransformer:
1594
+ """Create the appropriate transformer for a language"""
1595
+ if lang_support.language == SupportedLanguage.PYTHON:
1596
+ return PythonTransformer(lang_support)
1597
+ elif lang_support.language == SupportedLanguage.JAVASCRIPT:
1598
+ return JavaScriptTransformer(lang_support)
1599
+ elif lang_support.language == SupportedLanguage.JAVA:
1600
+ return JavaTransformer(lang_support)
1601
+ elif lang_support.language == SupportedLanguage.CSHARP:
1602
+ return CSharpTransformer(lang_support)
1603
+ elif lang_support.language == SupportedLanguage.CPP:
1604
+ return CppTransformer(lang_support)
1605
+ else:
1606
+ return LanguageTransformer(lang_support)
1607
+
1608
+
1609
+ def _init_languages() -> None:
1610
+ """Initialize all built-in language definitions"""
1611
+
1612
+ # Python
1613
+ python_syntax = LanguageSyntax(
1614
+ name="Python",
1615
+ statement_terminator="\n",
1616
+ uses_braces=False,
1617
+ boolean_true="True",
1618
+ boolean_false="False",
1619
+ null_keyword="None",
1620
+ variable_keywords=[],
1621
+ function_keywords=["def"],
1622
+ class_keywords=["class"],
1623
+ constructor_name="__init__",
1624
+ print_function="print",
1625
+ comment_single="#",
1626
+ comment_multi_start='"""',
1627
+ comment_multi_end='"""'
1628
+ )
1629
+ python_support = LanguageSupport(
1630
+ language=SupportedLanguage.PYTHON,
1631
+ syntax=python_syntax,
1632
+ name="Python"
1633
+ )
1634
+ register_language("python", python_support)
1635
+ register_language("py", python_support)
1636
+
1637
+ # Java
1638
+ java_syntax = LanguageSyntax(
1639
+ name="Java",
1640
+ statement_terminator=";",
1641
+ uses_braces=True,
1642
+ boolean_true="true",
1643
+ boolean_false="false",
1644
+ null_keyword="null",
1645
+ variable_keywords=["int", "String", "boolean", "float", "double", "var"],
1646
+ function_keywords=["public", "private", "protected", "static", "void"],
1647
+ class_keywords=["class", "interface", "enum"],
1648
+ constructor_name="<classname>",
1649
+ print_function="System.out.println",
1650
+ comment_single="//",
1651
+ comment_multi_start="/*",
1652
+ comment_multi_end="*/"
1653
+ )
1654
+ java_support = LanguageSupport(
1655
+ language=SupportedLanguage.JAVA,
1656
+ syntax=java_syntax,
1657
+ name="Java"
1658
+ )
1659
+ register_language("java", java_support)
1660
+
1661
+ # C#
1662
+ csharp_syntax = LanguageSyntax(
1663
+ name="C#",
1664
+ statement_terminator=";",
1665
+ uses_braces=True,
1666
+ boolean_true="true",
1667
+ boolean_false="false",
1668
+ null_keyword="null",
1669
+ variable_keywords=["int", "string", "bool", "float", "double", "var", "dynamic"],
1670
+ function_keywords=["public", "private", "protected", "static", "void", "async"],
1671
+ class_keywords=["class", "interface", "struct", "enum"],
1672
+ constructor_name="<classname>",
1673
+ print_function="Console.WriteLine",
1674
+ comment_single="//",
1675
+ comment_multi_start="/*",
1676
+ comment_multi_end="*/"
1677
+ )
1678
+ csharp_support = LanguageSupport(
1679
+ language=SupportedLanguage.CSHARP,
1680
+ syntax=csharp_syntax,
1681
+ name="C#"
1682
+ )
1683
+ register_language("c#", csharp_support)
1684
+ register_language("csharp", csharp_support)
1685
+
1686
+ # C++
1687
+ cpp_syntax = LanguageSyntax(
1688
+ name="C++",
1689
+ statement_terminator=";",
1690
+ uses_braces=True,
1691
+ boolean_true="true",
1692
+ boolean_false="false",
1693
+ null_keyword="nullptr",
1694
+ variable_keywords=["int", "string", "bool", "float", "double", "auto", "const"],
1695
+ function_keywords=["void", "int", "string", "bool", "float", "double", "auto"],
1696
+ class_keywords=["class", "struct"],
1697
+ constructor_name="<classname>",
1698
+ print_function="std::cout",
1699
+ comment_single="//",
1700
+ comment_multi_start="/*",
1701
+ comment_multi_end="*/"
1702
+ )
1703
+ cpp_support = LanguageSupport(
1704
+ language=SupportedLanguage.CPP,
1705
+ syntax=cpp_syntax,
1706
+ name="C++"
1707
+ )
1708
+ register_language("c++", cpp_support)
1709
+ register_language("cpp", cpp_support)
1710
+
1711
+ # JavaScript
1712
+ js_syntax = LanguageSyntax(
1713
+ name="JavaScript",
1714
+ statement_terminator=";",
1715
+ uses_braces=True,
1716
+ boolean_true="true",
1717
+ boolean_false="false",
1718
+ null_keyword="null",
1719
+ variable_keywords=["let", "const", "var"],
1720
+ function_keywords=["function", "async"],
1721
+ class_keywords=["class"],
1722
+ constructor_name="constructor",
1723
+ print_function="console.log",
1724
+ comment_single="//",
1725
+ comment_multi_start="/*",
1726
+ comment_multi_end="*/"
1727
+ )
1728
+ js_support = LanguageSupport(
1729
+ language=SupportedLanguage.JAVASCRIPT,
1730
+ syntax=js_syntax,
1731
+ name="JavaScript"
1732
+ )
1733
+ register_language("javascript", js_support)
1734
+ register_language("js", js_support)
1735
+
1736
+
1737
+ # Initialize languages on module load
1738
+ _init_languages()
1739
+
1740
+
1741
+ # Export public API
1742
+ __all__ = [
1743
+ 'SupportedLanguage',
1744
+ 'LanguageSyntax',
1745
+ 'LanguageSupport',
1746
+ 'LanguageTransformer',
1747
+ 'PythonTransformer',
1748
+ 'JavaScriptTransformer',
1749
+ 'JavaTransformer',
1750
+ 'CSharpTransformer',
1751
+ 'CppTransformer',
1752
+ 'register_language',
1753
+ 'get_language',
1754
+ 'list_languages',
1755
+ 'create_transformer',
1756
+ 'LANGUAGE_DEFINITIONS',
1757
+ ]