IncludeCPP 3.7.1__tar.gz → 3.7.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {includecpp-3.7.1 → includecpp-3.7.5}/IncludeCPP.egg-info/PKG-INFO +1 -1
- {includecpp-3.7.1 → includecpp-3.7.5}/PKG-INFO +1 -1
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/__init__.py +1 -1
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/cli/commands.py +111 -4
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/CSSL_DOCUMENTATION.md +1 -1
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/cssl_parser.py +132 -8
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/cssl_runtime.py +139 -13
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl_bridge.py +477 -48
- {includecpp-3.7.1 → includecpp-3.7.5}/pyproject.toml +1 -1
- {includecpp-3.7.1 → includecpp-3.7.5}/setup.py +1 -1
- {includecpp-3.7.1 → includecpp-3.7.5}/IncludeCPP.egg-info/SOURCES.txt +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/IncludeCPP.egg-info/dependency_links.txt +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/IncludeCPP.egg-info/entry_points.txt +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/IncludeCPP.egg-info/requires.txt +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/IncludeCPP.egg-info/top_level.txt +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/LICENSE +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/MANIFEST.in +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/README.md +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/__init__.pyi +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/__main__.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/cli/__init__.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/cli/config_parser.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/__init__.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/ai_integration.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/build_manager.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cpp_api.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cpp_api.pyi +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cppy_converter.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/__init__.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/cssl_builtins.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/cssl_builtins.pyi +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/cssl_events.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/cssl_modules.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/cssl_syntax.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl/cssl_types.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/cssl_bridge.pyi +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/error_catalog.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/error_formatter.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/exceptions.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/path_discovery.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/project_ui.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/core/settings_ui.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/generator/__init__.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/generator/parser.cpp +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/generator/parser.h +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/generator/type_resolver.cpp +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/generator/type_resolver.h +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/py.typed +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/templates/cpp.proj.template +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/vscode/__init__.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/vscode/cssl/__init__.py +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/vscode/cssl/language-configuration.json +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/vscode/cssl/package.json +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/vscode/cssl/snippets/cssl.snippets.json +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/requirements.txt +0 -0
- {includecpp-3.7.1 → includecpp-3.7.5}/setup.cfg +0 -0
|
@@ -7535,10 +7535,29 @@ def cssl_makemodule(path, output):
|
|
|
7535
7535
|
|
|
7536
7536
|
|
|
7537
7537
|
@cssl.command(name='doc')
|
|
7538
|
-
|
|
7539
|
-
|
|
7538
|
+
@click.argument('search', required=False, default=None)
|
|
7539
|
+
@click.option('--list', '-l', 'list_sections', is_flag=True, help='List all documentation sections')
|
|
7540
|
+
def cssl_doc(search, list_sections):
|
|
7541
|
+
"""Show CSSL documentation.
|
|
7542
|
+
|
|
7543
|
+
\b
|
|
7544
|
+
Usage:
|
|
7545
|
+
includecpp cssl doc # Show full documentation
|
|
7546
|
+
includecpp cssl doc "open" # Search for 'open' keyword
|
|
7547
|
+
includecpp cssl doc "$" # Search for shared variable syntax
|
|
7548
|
+
includecpp cssl doc "define" # Search for define keyword
|
|
7549
|
+
includecpp cssl doc --list # List all sections
|
|
7550
|
+
|
|
7551
|
+
\b
|
|
7552
|
+
Examples:
|
|
7553
|
+
includecpp cssl doc "class" # Show OOP/class documentation
|
|
7554
|
+
includecpp cssl doc "json::" # Show JSON functions
|
|
7555
|
+
includecpp cssl doc "this->" # Show this-> keyword usage
|
|
7556
|
+
includecpp cssl doc "map" # Show Map container docs
|
|
7557
|
+
"""
|
|
7540
7558
|
from pathlib import Path as PathLib
|
|
7541
7559
|
import os
|
|
7560
|
+
import re
|
|
7542
7561
|
|
|
7543
7562
|
# Find the documentation file in the cssl package directory
|
|
7544
7563
|
cssl_dir = PathLib(__file__).parent.parent / 'core' / 'cssl'
|
|
@@ -7558,8 +7577,96 @@ def cssl_doc():
|
|
|
7558
7577
|
|
|
7559
7578
|
if doc_path.exists():
|
|
7560
7579
|
content = doc_path.read_text(encoding='utf-8')
|
|
7561
|
-
|
|
7562
|
-
|
|
7580
|
+
|
|
7581
|
+
# List sections mode
|
|
7582
|
+
if list_sections:
|
|
7583
|
+
click.secho("CSSL Documentation Sections", fg='cyan', bold=True)
|
|
7584
|
+
click.secho("=" * 40, fg='cyan')
|
|
7585
|
+
sections = re.findall(r'^##\s+(.+)$', content, re.MULTILINE)
|
|
7586
|
+
for i, section in enumerate(sections, 1):
|
|
7587
|
+
click.echo(f" {i:2d}. {section}")
|
|
7588
|
+
click.echo()
|
|
7589
|
+
click.echo("Use: includecpp cssl doc \"<keyword>\" to search")
|
|
7590
|
+
return
|
|
7591
|
+
|
|
7592
|
+
# Search mode
|
|
7593
|
+
if search:
|
|
7594
|
+
click.secho(f"Searching for: '{search}'", fg='cyan', bold=True)
|
|
7595
|
+
click.secho("=" * 50, fg='cyan')
|
|
7596
|
+
click.echo()
|
|
7597
|
+
|
|
7598
|
+
# Split into sections (## headers)
|
|
7599
|
+
sections = re.split(r'(?=^## )', content, flags=re.MULTILINE)
|
|
7600
|
+
|
|
7601
|
+
found_sections = []
|
|
7602
|
+
for section in sections:
|
|
7603
|
+
if search.lower() in section.lower():
|
|
7604
|
+
found_sections.append(section)
|
|
7605
|
+
|
|
7606
|
+
if found_sections:
|
|
7607
|
+
# Also find specific lines with the search term
|
|
7608
|
+
all_lines = content.split('\n')
|
|
7609
|
+
matching_lines = []
|
|
7610
|
+
for i, line in enumerate(all_lines):
|
|
7611
|
+
if search.lower() in line.lower():
|
|
7612
|
+
# Get context (2 lines before and after)
|
|
7613
|
+
start = max(0, i - 2)
|
|
7614
|
+
end = min(len(all_lines), i + 3)
|
|
7615
|
+
context = '\n'.join(all_lines[start:end])
|
|
7616
|
+
if context not in matching_lines:
|
|
7617
|
+
matching_lines.append((i + 1, context))
|
|
7618
|
+
|
|
7619
|
+
# Show summary
|
|
7620
|
+
click.secho(f"Found in {len(found_sections)} section(s):", fg='green')
|
|
7621
|
+
for section in found_sections:
|
|
7622
|
+
# Extract section title
|
|
7623
|
+
title_match = re.match(r'^##\s+(.+)$', section, re.MULTILINE)
|
|
7624
|
+
if title_match:
|
|
7625
|
+
click.echo(f" - {title_match.group(1)}")
|
|
7626
|
+
|
|
7627
|
+
click.echo()
|
|
7628
|
+
|
|
7629
|
+
# Show matching contexts with highlighting
|
|
7630
|
+
click.secho("Matching content:", fg='yellow', bold=True)
|
|
7631
|
+
click.secho("-" * 50, fg='yellow')
|
|
7632
|
+
|
|
7633
|
+
for line_num, context in matching_lines[:15]: # Limit to 15 matches
|
|
7634
|
+
click.echo(f"\nLine {line_num}:")
|
|
7635
|
+
# Highlight the search term
|
|
7636
|
+
highlighted = re.sub(
|
|
7637
|
+
f'({re.escape(search)})',
|
|
7638
|
+
click.style(r'\1', fg='green', bold=True),
|
|
7639
|
+
context,
|
|
7640
|
+
flags=re.IGNORECASE
|
|
7641
|
+
)
|
|
7642
|
+
click.echo(highlighted)
|
|
7643
|
+
click.echo("-" * 30)
|
|
7644
|
+
|
|
7645
|
+
if len(matching_lines) > 15:
|
|
7646
|
+
click.echo(f"\n... and {len(matching_lines) - 15} more matches")
|
|
7647
|
+
|
|
7648
|
+
# Offer to show full sections
|
|
7649
|
+
click.echo()
|
|
7650
|
+
click.secho("Full sections containing your search:", fg='cyan')
|
|
7651
|
+
click.echo("(Scroll or pipe to a file for full content)")
|
|
7652
|
+
click.echo()
|
|
7653
|
+
|
|
7654
|
+
for section in found_sections:
|
|
7655
|
+
click.echo(section)
|
|
7656
|
+
click.echo()
|
|
7657
|
+
|
|
7658
|
+
else:
|
|
7659
|
+
click.secho(f"No matches found for '{search}'", fg='yellow')
|
|
7660
|
+
click.echo()
|
|
7661
|
+
click.echo("Try searching for:")
|
|
7662
|
+
click.echo(" - Keywords: class, function, define, open, global")
|
|
7663
|
+
click.echo(" - Syntax: $, @, ::, this->, <<==, <==")
|
|
7664
|
+
click.echo(" - Types: string, int, stack, vector, map, json")
|
|
7665
|
+
click.echo()
|
|
7666
|
+
click.echo("Or use: includecpp cssl doc --list")
|
|
7667
|
+
else:
|
|
7668
|
+
# Full documentation mode
|
|
7669
|
+
click.echo_via_pager(content)
|
|
7563
7670
|
else:
|
|
7564
7671
|
click.secho("Documentation file not found.", fg='yellow')
|
|
7565
7672
|
click.echo("Looking for: CSSL_DOCUMENTATION.md")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CSSL - C-Style Scripting Language
|
|
2
2
|
|
|
3
|
-
> Version 3.7.
|
|
3
|
+
> Version 3.7.2 | A modern scripting language with C++-style syntax and unique features like CodeInfusion and BruteInjection.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -108,6 +108,8 @@ class TokenType(Enum):
|
|
|
108
108
|
COMMENT = auto()
|
|
109
109
|
NEWLINE = auto()
|
|
110
110
|
EOF = auto()
|
|
111
|
+
# Super-functions for .cssl-pl payload files (v3.8.0)
|
|
112
|
+
SUPER_FUNC = auto() # #$run(), #$exec(), #$printl() - pre-execution hooks
|
|
111
113
|
|
|
112
114
|
|
|
113
115
|
KEYWORDS = {
|
|
@@ -212,9 +214,14 @@ class CSSLLexer:
|
|
|
212
214
|
|
|
213
215
|
char = self.source[self.pos]
|
|
214
216
|
|
|
215
|
-
# Comments
|
|
217
|
+
# Super-functions (#$) or Comments (# and // style)
|
|
216
218
|
if char == '#':
|
|
217
|
-
self.
|
|
219
|
+
if self._peek(1) == '$':
|
|
220
|
+
# Super-function: #$run(), #$exec(), #$printl()
|
|
221
|
+
self._read_super_function()
|
|
222
|
+
else:
|
|
223
|
+
# Regular comment
|
|
224
|
+
self._skip_comment()
|
|
218
225
|
elif char == '/' and self._peek(1) == '/':
|
|
219
226
|
# C-style // comment - NEW
|
|
220
227
|
self._skip_comment()
|
|
@@ -446,6 +453,31 @@ class CSSLLexer:
|
|
|
446
453
|
else:
|
|
447
454
|
self._add_token(TokenType.IDENTIFIER, value)
|
|
448
455
|
|
|
456
|
+
def _read_super_function(self):
|
|
457
|
+
"""Read #$<name>(...) super-function call for .cssl-pl payloads.
|
|
458
|
+
|
|
459
|
+
Super-functions are pre-execution hooks that run when a payload is loaded.
|
|
460
|
+
Valid super-functions: #$run(), #$exec(), #$printl()
|
|
461
|
+
|
|
462
|
+
Syntax:
|
|
463
|
+
#$run(initFunction); // Call a function at load time
|
|
464
|
+
#$exec(setup()); // Execute expression at load time
|
|
465
|
+
#$printl("Payload loaded"); // Print at load time
|
|
466
|
+
"""
|
|
467
|
+
start = self.pos
|
|
468
|
+
self._advance() # skip '#'
|
|
469
|
+
self._advance() # skip '$'
|
|
470
|
+
|
|
471
|
+
# Read the super-function name (run, exec, printl, etc.)
|
|
472
|
+
name_start = self.pos
|
|
473
|
+
while self.pos < len(self.source) and (self.source[self.pos].isalnum() or self.source[self.pos] == '_'):
|
|
474
|
+
self._advance()
|
|
475
|
+
func_name = self.source[name_start:self.pos]
|
|
476
|
+
|
|
477
|
+
# Store as #$<name> token value
|
|
478
|
+
value = f'#${func_name}'
|
|
479
|
+
self._add_token(TokenType.SUPER_FUNC, value)
|
|
480
|
+
|
|
449
481
|
def _read_self_ref(self):
|
|
450
482
|
"""Read s@<name> or s@<name>.<member>... self-reference"""
|
|
451
483
|
start = self.pos
|
|
@@ -1377,6 +1409,9 @@ class CSSLParser:
|
|
|
1377
1409
|
elif self._looks_like_function_declaration():
|
|
1378
1410
|
# Nested typed function (e.g., void Level2() { ... })
|
|
1379
1411
|
return self._parse_typed_function()
|
|
1412
|
+
elif self._check(TokenType.SUPER_FUNC):
|
|
1413
|
+
# Super-function for .cssl-pl payload files
|
|
1414
|
+
return self._parse_super_function()
|
|
1380
1415
|
elif (self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or
|
|
1381
1416
|
self._check(TokenType.CAPTURED_REF) or self._check(TokenType.SHARED_REF) or
|
|
1382
1417
|
self._check(TokenType.GLOBAL_REF) or self._check(TokenType.SELF_REF) or
|
|
@@ -1594,23 +1629,42 @@ class CSSLParser:
|
|
|
1594
1629
|
return ASTNode('c_for_update', value={'var': var_name, 'op': 'none'})
|
|
1595
1630
|
|
|
1596
1631
|
def _parse_python_style_for(self) -> ASTNode:
|
|
1597
|
-
"""Parse Python-style for loop: for (i in range(...)) { }
|
|
1632
|
+
"""Parse Python-style for loop: for (i in range(...)) { } or for (item in collection) { }
|
|
1598
1633
|
|
|
1599
1634
|
Supports:
|
|
1600
1635
|
for (i in range(n)) { } - 0 to n-1
|
|
1601
1636
|
for (i in range(start, end)) { } - start to end-1
|
|
1602
1637
|
for (i in range(start, end, step)) { }
|
|
1638
|
+
for (item in collection) { } - iterate over list/vector
|
|
1639
|
+
for (item in @global_collection) { } - iterate over global
|
|
1603
1640
|
"""
|
|
1604
1641
|
var_name = self._advance().value
|
|
1605
1642
|
self._expect(TokenType.KEYWORD) # 'in'
|
|
1606
1643
|
|
|
1607
|
-
#
|
|
1644
|
+
# Check if this is range() or collection iteration
|
|
1645
|
+
is_range = False
|
|
1608
1646
|
if self._check(TokenType.KEYWORD) and self._peek().value == 'range':
|
|
1609
1647
|
self._advance() # consume 'range' keyword
|
|
1648
|
+
is_range = True
|
|
1610
1649
|
elif self._check(TokenType.IDENTIFIER) and self._peek().value == 'range':
|
|
1611
1650
|
self._advance() # consume 'range' identifier
|
|
1612
|
-
|
|
1613
|
-
|
|
1651
|
+
is_range = True
|
|
1652
|
+
|
|
1653
|
+
# If not range, parse as collection iteration
|
|
1654
|
+
if not is_range:
|
|
1655
|
+
iterable = self._parse_expression()
|
|
1656
|
+
self._expect(TokenType.PAREN_END)
|
|
1657
|
+
|
|
1658
|
+
node = ASTNode('foreach', value={'var': var_name, 'iterable': iterable}, children=[])
|
|
1659
|
+
self._expect(TokenType.BLOCK_START)
|
|
1660
|
+
|
|
1661
|
+
while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
|
|
1662
|
+
stmt = self._parse_statement()
|
|
1663
|
+
if stmt:
|
|
1664
|
+
node.children.append(stmt)
|
|
1665
|
+
|
|
1666
|
+
self._expect(TokenType.BLOCK_END)
|
|
1667
|
+
return node
|
|
1614
1668
|
|
|
1615
1669
|
self._expect(TokenType.PAREN_START)
|
|
1616
1670
|
first_arg = self._parse_expression()
|
|
@@ -1728,6 +1782,31 @@ class CSSLParser:
|
|
|
1728
1782
|
self._match(TokenType.SEMICOLON)
|
|
1729
1783
|
return ASTNode('return', value=value)
|
|
1730
1784
|
|
|
1785
|
+
def _parse_super_function(self) -> ASTNode:
|
|
1786
|
+
"""Parse super-function for .cssl-pl payload files.
|
|
1787
|
+
|
|
1788
|
+
Syntax:
|
|
1789
|
+
#$run(initFunction); // Call function at load time
|
|
1790
|
+
#$exec(setup()); // Execute expression at load time
|
|
1791
|
+
#$printl("Payload loaded"); // Print at load time
|
|
1792
|
+
|
|
1793
|
+
These are pre-execution hooks that run when payload() loads the file.
|
|
1794
|
+
"""
|
|
1795
|
+
token = self._advance() # Get the SUPER_FUNC token
|
|
1796
|
+
super_name = token.value # e.g., "#$run", "#$exec", "#$printl"
|
|
1797
|
+
|
|
1798
|
+
# Parse the arguments
|
|
1799
|
+
self._expect(TokenType.PAREN_START)
|
|
1800
|
+
args = []
|
|
1801
|
+
if not self._check(TokenType.PAREN_END):
|
|
1802
|
+
args.append(self._parse_expression())
|
|
1803
|
+
while self._match(TokenType.COMMA):
|
|
1804
|
+
args.append(self._parse_expression())
|
|
1805
|
+
self._expect(TokenType.PAREN_END)
|
|
1806
|
+
self._match(TokenType.SEMICOLON)
|
|
1807
|
+
|
|
1808
|
+
return ASTNode('super_func', value={'name': super_name, 'args': args})
|
|
1809
|
+
|
|
1731
1810
|
def _parse_try(self) -> ASTNode:
|
|
1732
1811
|
node = ASTNode('try', children=[])
|
|
1733
1812
|
|
|
@@ -2335,17 +2414,62 @@ class CSSLParser:
|
|
|
2335
2414
|
self._expect(TokenType.COMPARE_GT) # consume >
|
|
2336
2415
|
return ASTNode('instance_ref', value=instance_name)
|
|
2337
2416
|
|
|
2338
|
-
# Check for type generic instantiation: stack<string>, vector<int>, etc.
|
|
2417
|
+
# Check for type generic instantiation: stack<string>, vector<int>, map<string, int>, etc.
|
|
2339
2418
|
# This creates a new instance of the type with the specified element type
|
|
2340
2419
|
if name in TYPE_GENERICS and self._check(TokenType.COMPARE_LT):
|
|
2341
2420
|
self._advance() # consume <
|
|
2342
2421
|
element_type = 'dynamic'
|
|
2422
|
+
value_type = None # For map<K, V>
|
|
2423
|
+
|
|
2343
2424
|
if self._check(TokenType.KEYWORD) or self._check(TokenType.IDENTIFIER):
|
|
2344
2425
|
element_type = self._advance().value
|
|
2426
|
+
|
|
2427
|
+
# Check for second type parameter (map<K, V>)
|
|
2428
|
+
if name == 'map' and self._check(TokenType.COMMA):
|
|
2429
|
+
self._advance() # consume ,
|
|
2430
|
+
if self._check(TokenType.KEYWORD) or self._check(TokenType.IDENTIFIER):
|
|
2431
|
+
value_type = self._advance().value
|
|
2432
|
+
else:
|
|
2433
|
+
value_type = 'dynamic'
|
|
2434
|
+
|
|
2345
2435
|
self._expect(TokenType.COMPARE_GT) # consume >
|
|
2436
|
+
|
|
2437
|
+
# Check for inline initialization: map<K,V>{"key": "value", ...}
|
|
2438
|
+
init_values = None
|
|
2439
|
+
if self._check(TokenType.BLOCK_START):
|
|
2440
|
+
self._advance() # consume {
|
|
2441
|
+
init_values = {}
|
|
2442
|
+
|
|
2443
|
+
while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
|
|
2444
|
+
# Parse key
|
|
2445
|
+
if self._check(TokenType.STRING):
|
|
2446
|
+
key = self._advance().value
|
|
2447
|
+
elif self._check(TokenType.IDENTIFIER):
|
|
2448
|
+
key = self._advance().value
|
|
2449
|
+
else:
|
|
2450
|
+
key = str(self._parse_expression().value) if hasattr(self._parse_expression(), 'value') else 'key'
|
|
2451
|
+
|
|
2452
|
+
# Expect : or =
|
|
2453
|
+
if self._check(TokenType.COLON):
|
|
2454
|
+
self._advance()
|
|
2455
|
+
elif self._check(TokenType.EQUALS):
|
|
2456
|
+
self._advance()
|
|
2457
|
+
|
|
2458
|
+
# Parse value
|
|
2459
|
+
value = self._parse_expression()
|
|
2460
|
+
init_values[key] = value
|
|
2461
|
+
|
|
2462
|
+
# Optional comma
|
|
2463
|
+
if self._check(TokenType.COMMA):
|
|
2464
|
+
self._advance()
|
|
2465
|
+
|
|
2466
|
+
self._expect(TokenType.BLOCK_END) # consume }
|
|
2467
|
+
|
|
2346
2468
|
return ASTNode('type_instantiation', value={
|
|
2347
2469
|
'type': name,
|
|
2348
|
-
'element_type': element_type
|
|
2470
|
+
'element_type': element_type,
|
|
2471
|
+
'value_type': value_type,
|
|
2472
|
+
'init_values': init_values
|
|
2349
2473
|
})
|
|
2350
2474
|
|
|
2351
2475
|
# Check for type-parameterized function call: OpenFind<string>(0)
|
|
@@ -401,6 +401,9 @@ class CSSLRuntime:
|
|
|
401
401
|
elif child.type == 'instance_declaration':
|
|
402
402
|
# Handle instance declaration: instance<"name"> varName;
|
|
403
403
|
result = self._exec_instance_declaration(child)
|
|
404
|
+
elif child.type == 'super_func':
|
|
405
|
+
# Super-function for .cssl-pl payload files (#$run, #$exec, #$printl)
|
|
406
|
+
result = self._exec_super_func(child)
|
|
404
407
|
elif child.type in ('assignment', 'expression', 'inject', 'receive', 'flow',
|
|
405
408
|
'if', 'while', 'for', 'c_for', 'foreach', 'switch', 'try'):
|
|
406
409
|
result = self._execute_node(child)
|
|
@@ -820,6 +823,82 @@ class CSSLRuntime:
|
|
|
820
823
|
self.scope.set(var_name, instance)
|
|
821
824
|
return instance
|
|
822
825
|
|
|
826
|
+
def _exec_super_func(self, node: ASTNode) -> Any:
|
|
827
|
+
"""Execute super-function for .cssl-pl payload files.
|
|
828
|
+
|
|
829
|
+
Super-functions are pre-execution hooks that run when payload() loads a file.
|
|
830
|
+
|
|
831
|
+
Supported super-functions:
|
|
832
|
+
#$run(funcName) - Call a function defined in the payload
|
|
833
|
+
#$exec(expression) - Execute an expression immediately
|
|
834
|
+
#$printl(message) - Print a message during load
|
|
835
|
+
|
|
836
|
+
Example .cssl-pl file:
|
|
837
|
+
void initDatabase() {
|
|
838
|
+
printl("DB initialized");
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
#$run(initDatabase); // Calls initDatabase when payload loads
|
|
842
|
+
#$printl("Payload loaded"); // Prints during load
|
|
843
|
+
"""
|
|
844
|
+
super_info = node.value
|
|
845
|
+
super_name = super_info.get('name', '') # e.g., "#$run", "#$exec", "#$printl"
|
|
846
|
+
args = super_info.get('args', [])
|
|
847
|
+
|
|
848
|
+
# Extract the function name part (after #$)
|
|
849
|
+
if super_name.startswith('#$'):
|
|
850
|
+
func_type = super_name[2:] # "run", "exec", "printl"
|
|
851
|
+
else:
|
|
852
|
+
func_type = super_name
|
|
853
|
+
|
|
854
|
+
if func_type == 'run':
|
|
855
|
+
# #$run(funcName) - Call a function by name
|
|
856
|
+
if args:
|
|
857
|
+
func_ref = args[0]
|
|
858
|
+
if isinstance(func_ref, ASTNode):
|
|
859
|
+
if func_ref.type == 'identifier':
|
|
860
|
+
func_name = func_ref.value
|
|
861
|
+
elif func_ref.type == 'call':
|
|
862
|
+
# Direct call like #$run(setup())
|
|
863
|
+
return self._eval_call(func_ref)
|
|
864
|
+
else:
|
|
865
|
+
func_name = self._evaluate(func_ref)
|
|
866
|
+
else:
|
|
867
|
+
func_name = str(func_ref)
|
|
868
|
+
|
|
869
|
+
# Look up and call the function
|
|
870
|
+
func_node = self.scope.get(func_name)
|
|
871
|
+
if func_node and isinstance(func_node, ASTNode) and func_node.type == 'function':
|
|
872
|
+
return self._call_function(func_node, [])
|
|
873
|
+
else:
|
|
874
|
+
raise CSSLRuntimeError(f"#$run: Function '{func_name}' not found", node.line)
|
|
875
|
+
|
|
876
|
+
elif func_type == 'exec':
|
|
877
|
+
# #$exec(expression) - Execute an expression
|
|
878
|
+
if args:
|
|
879
|
+
return self._evaluate(args[0])
|
|
880
|
+
|
|
881
|
+
elif func_type == 'printl':
|
|
882
|
+
# #$printl(message) - Print a message
|
|
883
|
+
if args:
|
|
884
|
+
msg = self._evaluate(args[0])
|
|
885
|
+
print(str(msg))
|
|
886
|
+
self.output_buffer.append(str(msg))
|
|
887
|
+
return None
|
|
888
|
+
|
|
889
|
+
elif func_type == 'print':
|
|
890
|
+
# #$print(message) - Print without newline
|
|
891
|
+
if args:
|
|
892
|
+
msg = self._evaluate(args[0])
|
|
893
|
+
print(str(msg), end='')
|
|
894
|
+
self.output_buffer.append(str(msg))
|
|
895
|
+
return None
|
|
896
|
+
|
|
897
|
+
else:
|
|
898
|
+
raise CSSLRuntimeError(f"Unknown super-function: {super_name}", node.line)
|
|
899
|
+
|
|
900
|
+
return None
|
|
901
|
+
|
|
823
902
|
def _exec_global_assignment(self, node: ASTNode) -> Any:
|
|
824
903
|
"""Execute global variable assignment: global Name = value
|
|
825
904
|
|
|
@@ -884,10 +963,20 @@ class CSSLRuntime:
|
|
|
884
963
|
|
|
885
964
|
# Bind parameters - handle both positional and named arguments
|
|
886
965
|
for i, param in enumerate(params):
|
|
887
|
-
# Extract param name from dict format: {'name': 'a', 'type': 'int'}
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
966
|
+
# Extract param name and type from dict format: {'name': 'a', 'type': 'int'}
|
|
967
|
+
if isinstance(param, dict):
|
|
968
|
+
param_name = param['name']
|
|
969
|
+
param_type = param.get('type', '')
|
|
970
|
+
else:
|
|
971
|
+
param_name = param
|
|
972
|
+
param_type = ''
|
|
973
|
+
|
|
974
|
+
# Check if this is an 'open' parameter - receives all args as a list
|
|
975
|
+
if param_type == 'open' or param_name == 'Params':
|
|
976
|
+
# 'open Params' receives all arguments as a list
|
|
977
|
+
new_scope.set(param_name, list(args))
|
|
978
|
+
new_scope.set('Params', list(args)) # Also set 'Params' for OpenFind
|
|
979
|
+
elif param_name in kwargs:
|
|
891
980
|
# Named argument takes priority
|
|
892
981
|
new_scope.set(param_name, kwargs[param_name])
|
|
893
982
|
elif i < len(args):
|
|
@@ -1778,9 +1867,12 @@ class CSSLRuntime:
|
|
|
1778
1867
|
|
|
1779
1868
|
if node.type == 'literal':
|
|
1780
1869
|
value = node.value
|
|
1781
|
-
#
|
|
1782
|
-
if isinstance(value, str)
|
|
1783
|
-
|
|
1870
|
+
# String interpolation - replace {var} or <var> with scope values
|
|
1871
|
+
if isinstance(value, str):
|
|
1872
|
+
has_fstring = '{' in value and '}' in value
|
|
1873
|
+
has_legacy = '<' in value and '>' in value
|
|
1874
|
+
if has_fstring or has_legacy:
|
|
1875
|
+
value = self._interpolate_string(value)
|
|
1784
1876
|
return value
|
|
1785
1877
|
|
|
1786
1878
|
# NEW: Type literals (list, dict) - create empty instances
|
|
@@ -1890,9 +1982,11 @@ class CSSLRuntime:
|
|
|
1890
1982
|
return self._eval_this_access(node)
|
|
1891
1983
|
|
|
1892
1984
|
if node.type == 'type_instantiation':
|
|
1893
|
-
# Create new instance of a type: stack<string>, vector<int>, etc.
|
|
1985
|
+
# Create new instance of a type: stack<string>, vector<int>, map<K,V>, etc.
|
|
1894
1986
|
type_name = node.value.get('type')
|
|
1895
1987
|
element_type = node.value.get('element_type', 'dynamic')
|
|
1988
|
+
value_type = node.value.get('value_type') # For map<K, V>
|
|
1989
|
+
init_values = node.value.get('init_values') # For inline init: map<K,V>{...}
|
|
1896
1990
|
|
|
1897
1991
|
if type_name == 'stack':
|
|
1898
1992
|
return Stack(element_type)
|
|
@@ -1916,6 +2010,15 @@ class CSSLRuntime:
|
|
|
1916
2010
|
return List(element_type)
|
|
1917
2011
|
elif type_name in ('dictionary', 'dict'):
|
|
1918
2012
|
return Dictionary(element_type)
|
|
2013
|
+
elif type_name == 'map':
|
|
2014
|
+
# Create Map with key_type and value_type
|
|
2015
|
+
m = Map(element_type, value_type or 'dynamic')
|
|
2016
|
+
# If inline initialization provided, populate the map
|
|
2017
|
+
if init_values:
|
|
2018
|
+
for key, value_node in init_values.items():
|
|
2019
|
+
value = self._evaluate(value_node)
|
|
2020
|
+
m.insert(key, value)
|
|
2021
|
+
return m
|
|
1919
2022
|
else:
|
|
1920
2023
|
return None
|
|
1921
2024
|
|
|
@@ -2714,14 +2817,24 @@ class CSSLRuntime:
|
|
|
2714
2817
|
elif isinstance(obj, dict):
|
|
2715
2818
|
obj[final_attr] = value
|
|
2716
2819
|
|
|
2717
|
-
#
|
|
2820
|
+
# String interpolation (supports both <var> and {var} syntax)
|
|
2718
2821
|
def _interpolate_string(self, string: str) -> str:
|
|
2719
|
-
"""Replace <variable> placeholders with values from scope
|
|
2822
|
+
"""Replace {variable} and <variable> placeholders with values from scope.
|
|
2823
|
+
|
|
2824
|
+
Both syntaxes are supported (variables only, not expressions):
|
|
2825
|
+
"Hello {name}!" -> "Hello John!" (f-string style)
|
|
2826
|
+
"Hello <name>!" -> "Hello John!" (legacy CSSL style)
|
|
2827
|
+
|
|
2828
|
+
Examples:
|
|
2829
|
+
string name = "Alice";
|
|
2830
|
+
int age = 30;
|
|
2831
|
+
printl("Hello {name}, you are {age} years old!");
|
|
2832
|
+
printl("Hello <name>, you are <age> years old!");
|
|
2720
2833
|
|
|
2721
|
-
|
|
2834
|
+
Note: Only simple variable names are supported, not expressions.
|
|
2835
|
+
Use string concatenation for complex expressions.
|
|
2722
2836
|
"""
|
|
2723
2837
|
import re
|
|
2724
|
-
pattern = r'<([A-Za-z_][A-Za-z0-9_]*)>'
|
|
2725
2838
|
|
|
2726
2839
|
def replacer(match):
|
|
2727
2840
|
var_name = match.group(1)
|
|
@@ -2733,10 +2846,23 @@ class CSSLRuntime:
|
|
|
2733
2846
|
# Try modules
|
|
2734
2847
|
if value is None:
|
|
2735
2848
|
value = self._modules.get(var_name)
|
|
2849
|
+
# Try global scope
|
|
2850
|
+
if value is None:
|
|
2851
|
+
value = self.global_scope.get(var_name)
|
|
2736
2852
|
# Return string representation or empty string if None
|
|
2737
2853
|
return str(value) if value is not None else ''
|
|
2738
2854
|
|
|
2739
|
-
|
|
2855
|
+
# Support both {var} and <var> syntax - simple variable names only
|
|
2856
|
+
# Pattern: {identifier} or <identifier>
|
|
2857
|
+
patterns = [
|
|
2858
|
+
r'\{([A-Za-z_][A-Za-z0-9_]*)\}', # {name} f-string style
|
|
2859
|
+
r'<([A-Za-z_][A-Za-z0-9_]*)>', # <name> legacy CSSL style
|
|
2860
|
+
]
|
|
2861
|
+
|
|
2862
|
+
result = string
|
|
2863
|
+
for pattern in patterns:
|
|
2864
|
+
result = re.sub(pattern, replacer, result)
|
|
2865
|
+
return result
|
|
2740
2866
|
|
|
2741
2867
|
# NEW: Promote variable to global scope via global()
|
|
2742
2868
|
def promote_to_global(self, s_ref_name: str):
|