IncludeCPP 3.6.0__tar.gz → 3.6.1__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.6.0 → includecpp-3.6.1}/IncludeCPP.egg-info/PKG-INFO +1 -1
- {includecpp-3.6.0 → includecpp-3.6.1}/PKG-INFO +1 -1
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/__init__.py +1 -1
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/CSSL_DOCUMENTATION.md +89 -13
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/cssl_builtins.py +95 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/cssl_parser.py +45 -46
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/cssl_runtime.py +51 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/pyproject.toml +1 -1
- {includecpp-3.6.0 → includecpp-3.6.1}/IncludeCPP.egg-info/SOURCES.txt +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/IncludeCPP.egg-info/dependency_links.txt +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/IncludeCPP.egg-info/entry_points.txt +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/IncludeCPP.egg-info/requires.txt +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/IncludeCPP.egg-info/top_level.txt +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/LICENSE +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/MANIFEST.in +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/README.md +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/__init__.pyi +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/__main__.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/cli/__init__.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/cli/commands.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/cli/config_parser.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/__init__.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/ai_integration.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/build_manager.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cpp_api.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cpp_api.pyi +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cppy_converter.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/__init__.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/cssl_events.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/cssl_modules.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/cssl_syntax.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl/cssl_types.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl_bridge.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/cssl_bridge.pyi +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/error_catalog.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/error_formatter.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/exceptions.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/path_discovery.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/project_ui.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/core/settings_ui.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/generator/__init__.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/generator/parser.cpp +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/generator/parser.h +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/generator/type_resolver.cpp +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/generator/type_resolver.h +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/py.typed +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/templates/cpp.proj.template +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/vscode/__init__.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/vscode/cssl/__init__.py +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/vscode/cssl/language-configuration.json +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/vscode/cssl/package.json +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/requirements.txt +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/setup.cfg +0 -0
- {includecpp-3.6.0 → includecpp-3.6.1}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CSSL - C-Style Scripting Language
|
|
2
2
|
|
|
3
|
-
> Version 3.6.
|
|
3
|
+
> Version 3.6.1 | A modern scripting language with C++-style syntax and unique features like CodeInfusion and BruteInjection.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -17,17 +17,18 @@
|
|
|
17
17
|
9. [String Methods](#string-methods)
|
|
18
18
|
10. [File I/O](#file-io)
|
|
19
19
|
11. [JSON Functions](#json-functions)
|
|
20
|
-
12. [
|
|
21
|
-
13. [
|
|
22
|
-
14. [
|
|
23
|
-
15. [
|
|
24
|
-
16. [
|
|
25
|
-
17. [
|
|
26
|
-
18. [
|
|
27
|
-
19. [
|
|
28
|
-
20. [
|
|
29
|
-
21. [
|
|
30
|
-
22. [
|
|
20
|
+
12. [Instance Management](#instance-management)
|
|
21
|
+
13. [Live Object Sharing](#live-object-sharing)
|
|
22
|
+
14. [CodeInfusion](#codeinfusion)
|
|
23
|
+
15. [Value Capture](#value-capture)
|
|
24
|
+
16. [BruteInjection](#bruteinjection)
|
|
25
|
+
17. [Filter Syntax](#filter-syntax)
|
|
26
|
+
18. [Module System](#module-system)
|
|
27
|
+
19. [Parameter Bridge](#parameter-bridge)
|
|
28
|
+
20. [Structures](#structures)
|
|
29
|
+
21. [Error Handling](#error-handling)
|
|
30
|
+
22. [CLI Commands](#cli-commands)
|
|
31
|
+
23. [Examples](#examples)
|
|
31
32
|
|
|
32
33
|
---
|
|
33
34
|
|
|
@@ -1000,6 +1001,81 @@ json merged = json::merge(obj1, obj2, obj3);
|
|
|
1000
1001
|
|
|
1001
1002
|
---
|
|
1002
1003
|
|
|
1004
|
+
## Instance Management
|
|
1005
|
+
|
|
1006
|
+
CSSL provides `instance<"name">` syntax and `instance::` namespace for working with shared instances.
|
|
1007
|
+
|
|
1008
|
+
### Instance Declaration
|
|
1009
|
+
|
|
1010
|
+
```cssl
|
|
1011
|
+
// Get/create shared instance by name
|
|
1012
|
+
instance<"MyApp"> app;
|
|
1013
|
+
|
|
1014
|
+
// With initialization
|
|
1015
|
+
instance<"tk"> tk = include("tkinter.cssl-mod");
|
|
1016
|
+
|
|
1017
|
+
// Register object as shared instance
|
|
1018
|
+
myModule ==> $AppModule
|
|
1019
|
+
// Or using instance syntax:
|
|
1020
|
+
myModule ==> instance<"AppModule">
|
|
1021
|
+
```
|
|
1022
|
+
|
|
1023
|
+
### Instance Introspection
|
|
1024
|
+
|
|
1025
|
+
```cssl
|
|
1026
|
+
@tk = include("tk.cssl-mod");
|
|
1027
|
+
|
|
1028
|
+
// Get all methods from module
|
|
1029
|
+
stack<string> methods = instance::getMethods(@tk);
|
|
1030
|
+
foreach (m in methods) {
|
|
1031
|
+
printl("Method: " + m);
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
// Get all classes
|
|
1035
|
+
stack<string> classes = instance::getClasses(@tk);
|
|
1036
|
+
|
|
1037
|
+
// Get all variables
|
|
1038
|
+
stack<string> vars = instance::getVars(@tk);
|
|
1039
|
+
|
|
1040
|
+
// Get everything categorized
|
|
1041
|
+
json all = instance::getAll(@tk);
|
|
1042
|
+
printl(all.methods); // ["method1", "method2", ...]
|
|
1043
|
+
printl(all.classes); // ["Class1", "Class2", ...]
|
|
1044
|
+
printl(all.vars); // ["var1", "var2", ...]
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
### Dynamic Method Calls
|
|
1048
|
+
|
|
1049
|
+
```cssl
|
|
1050
|
+
// Call method dynamically by name
|
|
1051
|
+
result = instance::call(@module, "methodName", arg1, arg2);
|
|
1052
|
+
|
|
1053
|
+
// Check if method/attribute exists
|
|
1054
|
+
if (instance::has(@module, "initialize")) {
|
|
1055
|
+
instance::call(@module, "initialize");
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// Get type name
|
|
1059
|
+
string typeName = instance::type(@module);
|
|
1060
|
+
printl(typeName); // "module"
|
|
1061
|
+
```
|
|
1062
|
+
|
|
1063
|
+
### All Instance Functions
|
|
1064
|
+
|
|
1065
|
+
| Function | Description |
|
|
1066
|
+
|----------|-------------|
|
|
1067
|
+
| `instance<"name"> var` | Declare instance variable |
|
|
1068
|
+
| `obj ==> instance<"name">` | Register as shared instance |
|
|
1069
|
+
| `instance::getMethods(obj)` | Get all method names |
|
|
1070
|
+
| `instance::getClasses(obj)` | Get all class names |
|
|
1071
|
+
| `instance::getVars(obj)` | Get all variable names |
|
|
1072
|
+
| `instance::getAll(obj)` | Get categorized dict |
|
|
1073
|
+
| `instance::call(obj, 'name', ...)` | Call method dynamically |
|
|
1074
|
+
| `instance::has(obj, 'name')` | Check if attribute exists |
|
|
1075
|
+
| `instance::type(obj)` | Get type name |
|
|
1076
|
+
|
|
1077
|
+
---
|
|
1078
|
+
|
|
1003
1079
|
## Live Object Sharing
|
|
1004
1080
|
|
|
1005
1081
|
Share Python objects with CSSL. Changes in CSSL reflect back to Python.
|
|
@@ -1810,4 +1886,4 @@ print(result) # ["Missing colon after def"]
|
|
|
1810
1886
|
|
|
1811
1887
|
---
|
|
1812
1888
|
|
|
1813
|
-
*CSSL v3.6.
|
|
1889
|
+
*CSSL v3.6.1 - Developed as part of IncludeCPP*
|
|
@@ -194,6 +194,15 @@ class CSSLBuiltins:
|
|
|
194
194
|
self._functions['json::has'] = self.builtin_json_has
|
|
195
195
|
self._functions['json::merge'] = self.builtin_json_merge
|
|
196
196
|
|
|
197
|
+
# Instance introspection functions (instance::getMethods, etc.)
|
|
198
|
+
self._functions['instance::getMethods'] = self.builtin_instance_getMethods
|
|
199
|
+
self._functions['instance::getClasses'] = self.builtin_instance_getClasses
|
|
200
|
+
self._functions['instance::getVars'] = self.builtin_instance_getVars
|
|
201
|
+
self._functions['instance::getAll'] = self.builtin_instance_getAll
|
|
202
|
+
self._functions['instance::call'] = self.builtin_instance_call
|
|
203
|
+
self._functions['instance::has'] = self.builtin_instance_has
|
|
204
|
+
self._functions['instance::type'] = self.builtin_instance_type
|
|
205
|
+
|
|
197
206
|
# Regex functions
|
|
198
207
|
self._functions['match'] = self.builtin_match
|
|
199
208
|
self._functions['search'] = self.builtin_search
|
|
@@ -1026,6 +1035,92 @@ class CSSLBuiltins:
|
|
|
1026
1035
|
result = deep_merge(result, d)
|
|
1027
1036
|
return result
|
|
1028
1037
|
|
|
1038
|
+
# ============= Instance Introspection Functions =============
|
|
1039
|
+
|
|
1040
|
+
def builtin_instance_getMethods(self, obj: Any) -> list:
|
|
1041
|
+
"""Get all methods from an object/module.
|
|
1042
|
+
Usage: instance::getMethods(@module) or instance::getMethods($obj)
|
|
1043
|
+
Returns list of method names.
|
|
1044
|
+
"""
|
|
1045
|
+
import inspect
|
|
1046
|
+
methods = []
|
|
1047
|
+
for name in dir(obj):
|
|
1048
|
+
if not name.startswith('_'):
|
|
1049
|
+
attr = getattr(obj, name, None)
|
|
1050
|
+
if callable(attr):
|
|
1051
|
+
methods.append(name)
|
|
1052
|
+
return methods
|
|
1053
|
+
|
|
1054
|
+
def builtin_instance_getClasses(self, obj: Any) -> list:
|
|
1055
|
+
"""Get all classes from an object/module.
|
|
1056
|
+
Usage: instance::getClasses(@module)
|
|
1057
|
+
Returns list of class names.
|
|
1058
|
+
"""
|
|
1059
|
+
import inspect
|
|
1060
|
+
classes = []
|
|
1061
|
+
for name in dir(obj):
|
|
1062
|
+
if not name.startswith('_'):
|
|
1063
|
+
attr = getattr(obj, name, None)
|
|
1064
|
+
if inspect.isclass(attr):
|
|
1065
|
+
classes.append(name)
|
|
1066
|
+
return classes
|
|
1067
|
+
|
|
1068
|
+
def builtin_instance_getVars(self, obj: Any) -> list:
|
|
1069
|
+
"""Get all variables/attributes (non-callable) from an object.
|
|
1070
|
+
Usage: instance::getVars(@module)
|
|
1071
|
+
Returns list of variable names.
|
|
1072
|
+
"""
|
|
1073
|
+
vars_list = []
|
|
1074
|
+
for name in dir(obj):
|
|
1075
|
+
if not name.startswith('_'):
|
|
1076
|
+
attr = getattr(obj, name, None)
|
|
1077
|
+
if not callable(attr):
|
|
1078
|
+
vars_list.append(name)
|
|
1079
|
+
return vars_list
|
|
1080
|
+
|
|
1081
|
+
def builtin_instance_getAll(self, obj: Any) -> dict:
|
|
1082
|
+
"""Get all attributes from an object, categorized.
|
|
1083
|
+
Usage: instance::getAll(@module)
|
|
1084
|
+
Returns dict with 'methods', 'classes', 'vars' keys.
|
|
1085
|
+
"""
|
|
1086
|
+
import inspect
|
|
1087
|
+
result = {
|
|
1088
|
+
'methods': [],
|
|
1089
|
+
'classes': [],
|
|
1090
|
+
'vars': []
|
|
1091
|
+
}
|
|
1092
|
+
for name in dir(obj):
|
|
1093
|
+
if not name.startswith('_'):
|
|
1094
|
+
attr = getattr(obj, name, None)
|
|
1095
|
+
if inspect.isclass(attr):
|
|
1096
|
+
result['classes'].append(name)
|
|
1097
|
+
elif callable(attr):
|
|
1098
|
+
result['methods'].append(name)
|
|
1099
|
+
else:
|
|
1100
|
+
result['vars'].append(name)
|
|
1101
|
+
return result
|
|
1102
|
+
|
|
1103
|
+
def builtin_instance_call(self, obj: Any, method_name: str, *args, **kwargs) -> Any:
|
|
1104
|
+
"""Dynamically call a method on an object.
|
|
1105
|
+
Usage: instance::call(@module, 'methodName', arg1, arg2)
|
|
1106
|
+
"""
|
|
1107
|
+
method = getattr(obj, method_name, None)
|
|
1108
|
+
if method and callable(method):
|
|
1109
|
+
return method(*args, **kwargs)
|
|
1110
|
+
raise RuntimeError(f"Method '{method_name}' not found on object")
|
|
1111
|
+
|
|
1112
|
+
def builtin_instance_has(self, obj: Any, name: str) -> bool:
|
|
1113
|
+
"""Check if object has an attribute.
|
|
1114
|
+
Usage: instance::has(@module, 'methodName')
|
|
1115
|
+
"""
|
|
1116
|
+
return hasattr(obj, name)
|
|
1117
|
+
|
|
1118
|
+
def builtin_instance_type(self, obj: Any) -> str:
|
|
1119
|
+
"""Get the type name of an object.
|
|
1120
|
+
Usage: instance::type(@module)
|
|
1121
|
+
"""
|
|
1122
|
+
return type(obj).__name__
|
|
1123
|
+
|
|
1029
1124
|
# ============= Regex Functions =============
|
|
1030
1125
|
|
|
1031
1126
|
def builtin_match(self, pattern: str, string: str) -> Optional[dict]:
|
|
@@ -898,7 +898,7 @@ class CSSLParser:
|
|
|
898
898
|
type_keywords = {'int', 'string', 'float', 'bool', 'dynamic', 'void',
|
|
899
899
|
'stack', 'vector', 'datastruct', 'dataspace', 'shuffled',
|
|
900
900
|
'iterator', 'combo', 'array', 'openquote', 'json',
|
|
901
|
-
'list', 'dictionary', 'dict'}
|
|
901
|
+
'list', 'dictionary', 'dict', 'instance'}
|
|
902
902
|
if type_name not in type_keywords:
|
|
903
903
|
return False
|
|
904
904
|
|
|
@@ -927,11 +927,13 @@ class CSSLParser:
|
|
|
927
927
|
# Get type name
|
|
928
928
|
type_name = self._advance().value # Consume type keyword
|
|
929
929
|
|
|
930
|
-
# Check for generic type <T>
|
|
930
|
+
# Check for generic type <T> or instance<"name">
|
|
931
931
|
element_type = None
|
|
932
932
|
if self._match(TokenType.COMPARE_LT):
|
|
933
|
-
#
|
|
934
|
-
if
|
|
933
|
+
# For instance<"name">, element_type can be a string literal
|
|
934
|
+
if type_name == 'instance' and self._check(TokenType.STRING):
|
|
935
|
+
element_type = self._advance().value
|
|
936
|
+
elif self._check(TokenType.KEYWORD) or self._check(TokenType.IDENTIFIER):
|
|
935
937
|
element_type = self._advance().value
|
|
936
938
|
self._expect(TokenType.COMPARE_GT)
|
|
937
939
|
|
|
@@ -947,6 +949,14 @@ class CSSLParser:
|
|
|
947
949
|
|
|
948
950
|
self._match(TokenType.SEMICOLON)
|
|
949
951
|
|
|
952
|
+
# For instance<"name">, create a special node type
|
|
953
|
+
if type_name == 'instance':
|
|
954
|
+
return ASTNode('instance_declaration', value={
|
|
955
|
+
'instance_name': element_type,
|
|
956
|
+
'name': var_name,
|
|
957
|
+
'value': value
|
|
958
|
+
})
|
|
959
|
+
|
|
950
960
|
return ASTNode('typed_declaration', value={
|
|
951
961
|
'type': type_name,
|
|
952
962
|
'element_type': element_type,
|
|
@@ -1992,14 +2002,10 @@ class CSSLParser:
|
|
|
1992
2002
|
# Continue to check for calls, indexing, member access on module refs
|
|
1993
2003
|
while True:
|
|
1994
2004
|
if self._match(TokenType.PAREN_START):
|
|
1995
|
-
# Function call on module ref: @Module.method()
|
|
1996
|
-
args =
|
|
1997
|
-
while not self._check(TokenType.PAREN_END) and not self._is_at_end():
|
|
1998
|
-
args.append(self._parse_expression())
|
|
1999
|
-
if not self._check(TokenType.PAREN_END):
|
|
2000
|
-
self._expect(TokenType.COMMA)
|
|
2005
|
+
# Function call on module ref: @Module.method() - with kwargs support
|
|
2006
|
+
args, kwargs = self._parse_call_arguments()
|
|
2001
2007
|
self._expect(TokenType.PAREN_END)
|
|
2002
|
-
node = ASTNode('call', value={'callee': node, 'args': args})
|
|
2008
|
+
node = ASTNode('call', value={'callee': node, 'args': args, 'kwargs': kwargs})
|
|
2003
2009
|
elif self._match(TokenType.DOT):
|
|
2004
2010
|
# Member access: @Module.property
|
|
2005
2011
|
member = self._advance().value
|
|
@@ -2017,31 +2023,23 @@ class CSSLParser:
|
|
|
2017
2023
|
# s@<name> self-reference to global struct
|
|
2018
2024
|
token = self._advance()
|
|
2019
2025
|
node = ASTNode('self_ref', value=token.value, line=token.line, column=token.column)
|
|
2020
|
-
# Check for function call: s@Backend.Loop.Start()
|
|
2026
|
+
# Check for function call: s@Backend.Loop.Start() - with kwargs support
|
|
2021
2027
|
if self._match(TokenType.PAREN_START):
|
|
2022
|
-
args =
|
|
2023
|
-
while not self._check(TokenType.PAREN_END):
|
|
2024
|
-
args.append(self._parse_expression())
|
|
2025
|
-
if not self._check(TokenType.PAREN_END):
|
|
2026
|
-
self._expect(TokenType.COMMA)
|
|
2028
|
+
args, kwargs = self._parse_call_arguments()
|
|
2027
2029
|
self._expect(TokenType.PAREN_END)
|
|
2028
|
-
node = ASTNode('call', value={'callee': node, 'args': args})
|
|
2030
|
+
node = ASTNode('call', value={'callee': node, 'args': args, 'kwargs': kwargs})
|
|
2029
2031
|
return node
|
|
2030
2032
|
|
|
2031
2033
|
if self._check(TokenType.GLOBAL_REF):
|
|
2032
2034
|
# r@<name> global variable reference/declaration
|
|
2033
2035
|
token = self._advance()
|
|
2034
2036
|
node = ASTNode('global_ref', value=token.value, line=token.line, column=token.column)
|
|
2035
|
-
# Check for member access, calls, indexing
|
|
2037
|
+
# Check for member access, calls, indexing - with kwargs support
|
|
2036
2038
|
while True:
|
|
2037
2039
|
if self._match(TokenType.PAREN_START):
|
|
2038
|
-
args =
|
|
2039
|
-
while not self._check(TokenType.PAREN_END):
|
|
2040
|
-
args.append(self._parse_expression())
|
|
2041
|
-
if not self._check(TokenType.PAREN_END):
|
|
2042
|
-
self._expect(TokenType.COMMA)
|
|
2040
|
+
args, kwargs = self._parse_call_arguments()
|
|
2043
2041
|
self._expect(TokenType.PAREN_END)
|
|
2044
|
-
node = ASTNode('call', value={'callee': node, 'args': args})
|
|
2042
|
+
node = ASTNode('call', value={'callee': node, 'args': args, 'kwargs': kwargs})
|
|
2045
2043
|
elif self._match(TokenType.DOT):
|
|
2046
2044
|
member = self._advance().value
|
|
2047
2045
|
node = ASTNode('member_access', value={'object': node, 'member': member})
|
|
@@ -2057,16 +2055,12 @@ class CSSLParser:
|
|
|
2057
2055
|
# $<name> shared object reference
|
|
2058
2056
|
token = self._advance()
|
|
2059
2057
|
node = ASTNode('shared_ref', value=token.value, line=token.line, column=token.column)
|
|
2060
|
-
# Check for member access, calls, indexing
|
|
2058
|
+
# Check for member access, calls, indexing - with kwargs support
|
|
2061
2059
|
while True:
|
|
2062
2060
|
if self._match(TokenType.PAREN_START):
|
|
2063
|
-
args =
|
|
2064
|
-
while not self._check(TokenType.PAREN_END):
|
|
2065
|
-
args.append(self._parse_expression())
|
|
2066
|
-
if not self._check(TokenType.PAREN_END):
|
|
2067
|
-
self._expect(TokenType.COMMA)
|
|
2061
|
+
args, kwargs = self._parse_call_arguments()
|
|
2068
2062
|
self._expect(TokenType.PAREN_END)
|
|
2069
|
-
node = ASTNode('call', value={'callee': node, 'args': args})
|
|
2063
|
+
node = ASTNode('call', value={'callee': node, 'args': args, 'kwargs': kwargs})
|
|
2070
2064
|
elif self._match(TokenType.DOT):
|
|
2071
2065
|
member = self._advance().value
|
|
2072
2066
|
node = ASTNode('member_access', value={'object': node, 'member': member})
|
|
@@ -2082,16 +2076,12 @@ class CSSLParser:
|
|
|
2082
2076
|
# %<name> captured reference (captures value at infusion registration time)
|
|
2083
2077
|
token = self._advance()
|
|
2084
2078
|
node = ASTNode('captured_ref', value=token.value, line=token.line, column=token.column)
|
|
2085
|
-
# Check for member access, calls, indexing
|
|
2079
|
+
# Check for member access, calls, indexing - with kwargs support
|
|
2086
2080
|
while True:
|
|
2087
2081
|
if self._match(TokenType.PAREN_START):
|
|
2088
|
-
args =
|
|
2089
|
-
while not self._check(TokenType.PAREN_END):
|
|
2090
|
-
args.append(self._parse_expression())
|
|
2091
|
-
if not self._check(TokenType.PAREN_END):
|
|
2092
|
-
self._expect(TokenType.COMMA)
|
|
2082
|
+
args, kwargs = self._parse_call_arguments()
|
|
2093
2083
|
self._expect(TokenType.PAREN_END)
|
|
2094
|
-
node = ASTNode('call', value={'callee': node, 'args': args})
|
|
2084
|
+
node = ASTNode('call', value={'callee': node, 'args': args, 'kwargs': kwargs})
|
|
2095
2085
|
elif self._match(TokenType.DOT):
|
|
2096
2086
|
member = self._advance().value
|
|
2097
2087
|
node = ASTNode('member_access', value={'object': node, 'member': member})
|
|
@@ -2160,14 +2150,10 @@ class CSSLParser:
|
|
|
2160
2150
|
member = self._advance().value
|
|
2161
2151
|
node = ASTNode('member_access', value={'object': node, 'member': member})
|
|
2162
2152
|
elif self._match(TokenType.PAREN_START):
|
|
2163
|
-
# Function call
|
|
2164
|
-
args =
|
|
2165
|
-
while not self._check(TokenType.PAREN_END):
|
|
2166
|
-
args.append(self._parse_expression())
|
|
2167
|
-
if not self._check(TokenType.PAREN_END):
|
|
2168
|
-
self._expect(TokenType.COMMA)
|
|
2153
|
+
# Function call - use _parse_call_arguments for kwargs support
|
|
2154
|
+
args, kwargs = self._parse_call_arguments()
|
|
2169
2155
|
self._expect(TokenType.PAREN_END)
|
|
2170
|
-
node = ASTNode('call', value={'callee': node, 'args': args})
|
|
2156
|
+
node = ASTNode('call', value={'callee': node, 'args': args, 'kwargs': kwargs})
|
|
2171
2157
|
elif self._match(TokenType.BRACKET_START):
|
|
2172
2158
|
# Index access
|
|
2173
2159
|
index = self._parse_expression()
|
|
@@ -2220,6 +2206,19 @@ class CSSLParser:
|
|
|
2220
2206
|
namespace_member = self._advance().value
|
|
2221
2207
|
name = f"{name}::{namespace_member}"
|
|
2222
2208
|
|
|
2209
|
+
# Check for instance<"name"> syntax - gets/creates shared instance
|
|
2210
|
+
if name == 'instance' and self._check(TokenType.COMPARE_LT):
|
|
2211
|
+
self._advance() # consume <
|
|
2212
|
+
# Expect string literal for instance name
|
|
2213
|
+
if self._check(TokenType.STRING):
|
|
2214
|
+
instance_name = self._advance().value
|
|
2215
|
+
elif self._check(TokenType.IDENTIFIER):
|
|
2216
|
+
instance_name = self._advance().value
|
|
2217
|
+
else:
|
|
2218
|
+
raise CSSLParserError("Expected instance name (string or identifier)", self._current_line())
|
|
2219
|
+
self._expect(TokenType.COMPARE_GT) # consume >
|
|
2220
|
+
return ASTNode('instance_ref', value=instance_name)
|
|
2221
|
+
|
|
2223
2222
|
# Check for type generic instantiation: stack<string>, vector<int>, etc.
|
|
2224
2223
|
# This creates a new instance of the type with the specified element type
|
|
2225
2224
|
if name in TYPE_GENERICS and self._check(TokenType.COMPARE_LT):
|
|
@@ -394,6 +394,9 @@ class CSSLRuntime:
|
|
|
394
394
|
elif child.type == 'typed_declaration':
|
|
395
395
|
# Handle typed variable declaration: type<T> varName = value;
|
|
396
396
|
result = self._exec_typed_declaration(child)
|
|
397
|
+
elif child.type == 'instance_declaration':
|
|
398
|
+
# Handle instance declaration: instance<"name"> varName;
|
|
399
|
+
result = self._exec_instance_declaration(child)
|
|
397
400
|
elif child.type in ('assignment', 'expression', 'inject', 'receive', 'flow',
|
|
398
401
|
'if', 'while', 'for', 'c_for', 'foreach', 'switch', 'try'):
|
|
399
402
|
result = self._execute_node(child)
|
|
@@ -732,6 +735,34 @@ class CSSLRuntime:
|
|
|
732
735
|
self.scope.set(var_name, instance)
|
|
733
736
|
return instance
|
|
734
737
|
|
|
738
|
+
def _exec_instance_declaration(self, node: ASTNode) -> Any:
|
|
739
|
+
"""Execute instance declaration: instance<"name"> varName;
|
|
740
|
+
|
|
741
|
+
Gets or creates a shared instance by name.
|
|
742
|
+
"""
|
|
743
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
744
|
+
decl = node.value
|
|
745
|
+
instance_name = decl.get('instance_name')
|
|
746
|
+
var_name = decl.get('name')
|
|
747
|
+
value_node = decl.get('value')
|
|
748
|
+
|
|
749
|
+
# Get existing shared instance
|
|
750
|
+
instance = None
|
|
751
|
+
if instance_name in _live_objects:
|
|
752
|
+
instance = SharedObjectProxy(instance_name, _live_objects[instance_name])
|
|
753
|
+
elif f'${instance_name}' in self.global_scope:
|
|
754
|
+
instance = self.global_scope.get(f'${instance_name}')
|
|
755
|
+
|
|
756
|
+
# If value is provided, use that and register as shared
|
|
757
|
+
if value_node:
|
|
758
|
+
instance = self._evaluate(value_node)
|
|
759
|
+
# Register in global scope for future access
|
|
760
|
+
self.global_scope.set(f'${instance_name}', instance)
|
|
761
|
+
|
|
762
|
+
# Store in scope
|
|
763
|
+
self.scope.set(var_name, instance)
|
|
764
|
+
return instance
|
|
765
|
+
|
|
735
766
|
def _exec_global_assignment(self, node: ASTNode) -> Any:
|
|
736
767
|
"""Execute global variable assignment: global Name = value
|
|
737
768
|
|
|
@@ -1471,6 +1502,12 @@ class CSSLRuntime:
|
|
|
1471
1502
|
name = target.value
|
|
1472
1503
|
_live_objects[name] = final_value
|
|
1473
1504
|
self.global_scope.set(f'${name}', SharedObjectProxy(name, final_value))
|
|
1505
|
+
elif target.type == 'instance_ref':
|
|
1506
|
+
# value ==> instance<"name"> - create/update shared object
|
|
1507
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
1508
|
+
name = target.value
|
|
1509
|
+
_live_objects[name] = final_value
|
|
1510
|
+
self.global_scope.set(f'${name}', SharedObjectProxy(name, final_value))
|
|
1474
1511
|
elif target.type == 'member_access':
|
|
1475
1512
|
self._set_member(target, final_value)
|
|
1476
1513
|
|
|
@@ -1767,6 +1804,20 @@ class CSSLRuntime:
|
|
|
1767
1804
|
return value
|
|
1768
1805
|
raise CSSLRuntimeError(f"Captured reference '%{name}' not found.")
|
|
1769
1806
|
|
|
1807
|
+
if node.type == 'instance_ref':
|
|
1808
|
+
# instance<"name"> - get shared instance by name
|
|
1809
|
+
# Works like $name but with explicit syntax
|
|
1810
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
1811
|
+
name = node.value
|
|
1812
|
+
if name in _live_objects:
|
|
1813
|
+
return SharedObjectProxy(name, _live_objects[name])
|
|
1814
|
+
# Check if stored in runtime's scope
|
|
1815
|
+
scoped_val = self.global_scope.get(f'${name}')
|
|
1816
|
+
if scoped_val is not None:
|
|
1817
|
+
return scoped_val
|
|
1818
|
+
# Return None if instance doesn't exist (can be created via ==>)
|
|
1819
|
+
return None
|
|
1820
|
+
|
|
1770
1821
|
if node.type == 'type_instantiation':
|
|
1771
1822
|
# Create new instance of a type: stack<string>, vector<int>, etc.
|
|
1772
1823
|
type_name = node.value.get('type')
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "IncludeCPP"
|
|
7
|
-
version = "3.6.
|
|
7
|
+
version = "3.6.1"
|
|
8
8
|
description = "Professional C++ Python bindings with type-generic templates, pystubs and native threading"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|