IncludeCPP 3.6.0__py3-none-any.whl → 3.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- includecpp/__init__.py +1 -1
- includecpp/cli/commands.py +418 -0
- includecpp/core/cssl/CSSL_DOCUMENTATION.md +275 -13
- includecpp/core/cssl/cssl_builtins.py +114 -0
- includecpp/core/cssl/cssl_builtins.pyi +1393 -0
- includecpp/core/cssl/cssl_parser.py +174 -59
- includecpp/core/cssl/cssl_runtime.py +273 -1
- includecpp/core/cssl/cssl_types.py +224 -2
- includecpp/vscode/cssl/package.json +24 -4
- includecpp/vscode/cssl/snippets/cssl.snippets.json +1080 -0
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +127 -7
- {includecpp-3.6.0.dist-info → includecpp-3.7.1.dist-info}/METADATA +1 -1
- {includecpp-3.6.0.dist-info → includecpp-3.7.1.dist-info}/RECORD +17 -15
- {includecpp-3.6.0.dist-info → includecpp-3.7.1.dist-info}/WHEEL +0 -0
- {includecpp-3.6.0.dist-info → includecpp-3.7.1.dist-info}/entry_points.txt +0 -0
- {includecpp-3.6.0.dist-info → includecpp-3.7.1.dist-info}/licenses/LICENSE +0 -0
- {includecpp-3.6.0.dist-info → includecpp-3.7.1.dist-info}/top_level.txt +0 -0
|
@@ -14,7 +14,8 @@ from .cssl_builtins import CSSLBuiltins
|
|
|
14
14
|
from .cssl_modules import get_module_registry, get_standard_module
|
|
15
15
|
from .cssl_types import (
|
|
16
16
|
Parameter, DataStruct, Shuffled, Iterator, Combo,
|
|
17
|
-
Stack, Vector, Array, DataSpace, OpenQuote, List, Dictionary
|
|
17
|
+
Stack, Vector, Array, DataSpace, OpenQuote, List, Dictionary, Map,
|
|
18
|
+
CSSLClass, CSSLInstance
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
|
|
@@ -145,6 +146,7 @@ class CSSLRuntime:
|
|
|
145
146
|
self._injection_captures: Dict[str, Dict[str, Any]] = {} # Captured %vars per injection
|
|
146
147
|
self._current_captured_values: Dict[str, Any] = {} # Current captured values during injection execution
|
|
147
148
|
self._promoted_globals: Dict[str, Any] = {} # NEW: Variables promoted via global()
|
|
149
|
+
self._current_instance: Optional[CSSLInstance] = None # Current class instance for this-> access
|
|
148
150
|
self._running = False
|
|
149
151
|
self._exit_code = 0
|
|
150
152
|
self._output_callback = output_callback # Callback for console output (text, level)
|
|
@@ -386,6 +388,8 @@ class CSSLRuntime:
|
|
|
386
388
|
|
|
387
389
|
if child.type == 'struct':
|
|
388
390
|
self._exec_struct(child)
|
|
391
|
+
elif child.type == 'class':
|
|
392
|
+
self._exec_class(child)
|
|
389
393
|
elif child.type == 'function':
|
|
390
394
|
self._exec_function(child)
|
|
391
395
|
elif child.type == 'global_assignment':
|
|
@@ -394,6 +398,9 @@ class CSSLRuntime:
|
|
|
394
398
|
elif child.type == 'typed_declaration':
|
|
395
399
|
# Handle typed variable declaration: type<T> varName = value;
|
|
396
400
|
result = self._exec_typed_declaration(child)
|
|
401
|
+
elif child.type == 'instance_declaration':
|
|
402
|
+
# Handle instance declaration: instance<"name"> varName;
|
|
403
|
+
result = self._exec_instance_declaration(child)
|
|
397
404
|
elif child.type in ('assignment', 'expression', 'inject', 'receive', 'flow',
|
|
398
405
|
'if', 'while', 'for', 'c_for', 'foreach', 'switch', 'try'):
|
|
399
406
|
result = self._execute_node(child)
|
|
@@ -661,6 +668,57 @@ class CSSLRuntime:
|
|
|
661
668
|
|
|
662
669
|
return struct_data
|
|
663
670
|
|
|
671
|
+
def _exec_class(self, node: ASTNode) -> CSSLClass:
|
|
672
|
+
"""Execute class definition - registers class in scope.
|
|
673
|
+
|
|
674
|
+
Parses class members and methods, creating a CSSLClass object
|
|
675
|
+
that can be instantiated with 'new'.
|
|
676
|
+
"""
|
|
677
|
+
class_info = node.value
|
|
678
|
+
class_name = class_info.get('name')
|
|
679
|
+
|
|
680
|
+
members = {} # Member variable defaults/types
|
|
681
|
+
methods = {} # Method AST nodes
|
|
682
|
+
constructor = None
|
|
683
|
+
|
|
684
|
+
for child in node.children:
|
|
685
|
+
if child.type == 'function':
|
|
686
|
+
# This is a method
|
|
687
|
+
func_info = child.value
|
|
688
|
+
method_name = func_info.get('name')
|
|
689
|
+
|
|
690
|
+
if func_info.get('is_constructor') or method_name == class_name or method_name == '__init__':
|
|
691
|
+
constructor = child
|
|
692
|
+
else:
|
|
693
|
+
methods[method_name] = child
|
|
694
|
+
|
|
695
|
+
elif child.type == 'typed_declaration':
|
|
696
|
+
# This is a member variable
|
|
697
|
+
decl = child.value
|
|
698
|
+
member_name = decl.get('name')
|
|
699
|
+
member_type = decl.get('type')
|
|
700
|
+
member_value = decl.get('value')
|
|
701
|
+
|
|
702
|
+
# Store member info with type and optional default
|
|
703
|
+
members[member_name] = {
|
|
704
|
+
'type': member_type,
|
|
705
|
+
'default': self._evaluate(member_value) if member_value else None
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
# Create class definition object
|
|
709
|
+
class_def = CSSLClass(
|
|
710
|
+
name=class_name,
|
|
711
|
+
members=members,
|
|
712
|
+
methods=methods,
|
|
713
|
+
constructor=constructor
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
# Register class in scope
|
|
717
|
+
self.scope.set(class_name, class_def)
|
|
718
|
+
self.global_scope.set(class_name, class_def)
|
|
719
|
+
|
|
720
|
+
return class_def
|
|
721
|
+
|
|
664
722
|
def _exec_function(self, node: ASTNode) -> Any:
|
|
665
723
|
"""Execute function definition - just registers it"""
|
|
666
724
|
func_info = node.value
|
|
@@ -714,6 +772,8 @@ class CSSLRuntime:
|
|
|
714
772
|
instance = List(element_type)
|
|
715
773
|
elif type_name in ('dictionary', 'dict'):
|
|
716
774
|
instance = Dictionary(element_type)
|
|
775
|
+
elif type_name == 'map':
|
|
776
|
+
instance = Map(element_type)
|
|
717
777
|
else:
|
|
718
778
|
# Default: evaluate the value or set to None
|
|
719
779
|
instance = self._evaluate(value_node) if value_node else None
|
|
@@ -732,6 +792,34 @@ class CSSLRuntime:
|
|
|
732
792
|
self.scope.set(var_name, instance)
|
|
733
793
|
return instance
|
|
734
794
|
|
|
795
|
+
def _exec_instance_declaration(self, node: ASTNode) -> Any:
|
|
796
|
+
"""Execute instance declaration: instance<"name"> varName;
|
|
797
|
+
|
|
798
|
+
Gets or creates a shared instance by name.
|
|
799
|
+
"""
|
|
800
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
801
|
+
decl = node.value
|
|
802
|
+
instance_name = decl.get('instance_name')
|
|
803
|
+
var_name = decl.get('name')
|
|
804
|
+
value_node = decl.get('value')
|
|
805
|
+
|
|
806
|
+
# Get existing shared instance
|
|
807
|
+
instance = None
|
|
808
|
+
if instance_name in _live_objects:
|
|
809
|
+
instance = SharedObjectProxy(instance_name, _live_objects[instance_name])
|
|
810
|
+
elif self.global_scope.has(f'${instance_name}'):
|
|
811
|
+
instance = self.global_scope.get(f'${instance_name}')
|
|
812
|
+
|
|
813
|
+
# If value is provided, use that and register as shared
|
|
814
|
+
if value_node:
|
|
815
|
+
instance = self._evaluate(value_node)
|
|
816
|
+
# Register in global scope for future access
|
|
817
|
+
self.global_scope.set(f'${instance_name}', instance)
|
|
818
|
+
|
|
819
|
+
# Store in scope
|
|
820
|
+
self.scope.set(var_name, instance)
|
|
821
|
+
return instance
|
|
822
|
+
|
|
735
823
|
def _exec_global_assignment(self, node: ASTNode) -> Any:
|
|
736
824
|
"""Execute global variable assignment: global Name = value
|
|
737
825
|
|
|
@@ -1471,6 +1559,12 @@ class CSSLRuntime:
|
|
|
1471
1559
|
name = target.value
|
|
1472
1560
|
_live_objects[name] = final_value
|
|
1473
1561
|
self.global_scope.set(f'${name}', SharedObjectProxy(name, final_value))
|
|
1562
|
+
elif target.type == 'instance_ref':
|
|
1563
|
+
# value ==> instance<"name"> - create/update shared object
|
|
1564
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
1565
|
+
name = target.value
|
|
1566
|
+
_live_objects[name] = final_value
|
|
1567
|
+
self.global_scope.set(f'${name}', SharedObjectProxy(name, final_value))
|
|
1474
1568
|
elif target.type == 'member_access':
|
|
1475
1569
|
self._set_member(target, final_value)
|
|
1476
1570
|
|
|
@@ -1620,6 +1714,12 @@ class CSSLRuntime:
|
|
|
1620
1714
|
self._set_member(target, value)
|
|
1621
1715
|
elif target.type == 'index_access':
|
|
1622
1716
|
self._set_index(target, value)
|
|
1717
|
+
elif target.type == 'this_access':
|
|
1718
|
+
# this->member = value
|
|
1719
|
+
if self._current_instance is None:
|
|
1720
|
+
raise CSSLRuntimeError("'this' used outside of class method context")
|
|
1721
|
+
member = target.value.get('member')
|
|
1722
|
+
self._current_instance.set_member(member, value)
|
|
1623
1723
|
elif isinstance(target, str):
|
|
1624
1724
|
self.scope.set(target, value)
|
|
1625
1725
|
|
|
@@ -1767,6 +1867,28 @@ class CSSLRuntime:
|
|
|
1767
1867
|
return value
|
|
1768
1868
|
raise CSSLRuntimeError(f"Captured reference '%{name}' not found.")
|
|
1769
1869
|
|
|
1870
|
+
if node.type == 'instance_ref':
|
|
1871
|
+
# instance<"name"> - get shared instance by name
|
|
1872
|
+
# Works like $name but with explicit syntax
|
|
1873
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
1874
|
+
name = node.value
|
|
1875
|
+
if name in _live_objects:
|
|
1876
|
+
return SharedObjectProxy(name, _live_objects[name])
|
|
1877
|
+
# Check if stored in runtime's scope
|
|
1878
|
+
scoped_val = self.global_scope.get(f'${name}')
|
|
1879
|
+
if scoped_val is not None:
|
|
1880
|
+
return scoped_val
|
|
1881
|
+
# Return None if instance doesn't exist (can be created via ==>)
|
|
1882
|
+
return None
|
|
1883
|
+
|
|
1884
|
+
if node.type == 'new':
|
|
1885
|
+
# Create new instance of a class: new ClassName(args)
|
|
1886
|
+
return self._eval_new(node)
|
|
1887
|
+
|
|
1888
|
+
if node.type == 'this_access':
|
|
1889
|
+
# this->member access
|
|
1890
|
+
return self._eval_this_access(node)
|
|
1891
|
+
|
|
1770
1892
|
if node.type == 'type_instantiation':
|
|
1771
1893
|
# Create new instance of a type: stack<string>, vector<int>, etc.
|
|
1772
1894
|
type_name = node.value.get('type')
|
|
@@ -2136,6 +2258,140 @@ class CSSLRuntime:
|
|
|
2136
2258
|
hint="Typed functions use format: FunctionName<Type>(args)"
|
|
2137
2259
|
)
|
|
2138
2260
|
|
|
2261
|
+
def _eval_new(self, node: ASTNode) -> CSSLInstance:
|
|
2262
|
+
"""Evaluate 'new ClassName(args)' expression.
|
|
2263
|
+
|
|
2264
|
+
Creates a new instance of a CSSL class and calls its constructor.
|
|
2265
|
+
"""
|
|
2266
|
+
class_name = node.value.get('class')
|
|
2267
|
+
args = [self._evaluate(arg) for arg in node.value.get('args', [])]
|
|
2268
|
+
kwargs = {k: self._evaluate(v) for k, v in node.value.get('kwargs', {}).items()}
|
|
2269
|
+
|
|
2270
|
+
# Get class definition from scope
|
|
2271
|
+
class_def = self.scope.get(class_name)
|
|
2272
|
+
if class_def is None:
|
|
2273
|
+
class_def = self.global_scope.get(class_name)
|
|
2274
|
+
|
|
2275
|
+
if class_def is None:
|
|
2276
|
+
raise CSSLRuntimeError(
|
|
2277
|
+
f"Class '{class_name}' not found",
|
|
2278
|
+
node.line,
|
|
2279
|
+
hint="Make sure the class is defined before instantiation"
|
|
2280
|
+
)
|
|
2281
|
+
|
|
2282
|
+
if not isinstance(class_def, CSSLClass):
|
|
2283
|
+
raise CSSLRuntimeError(
|
|
2284
|
+
f"'{class_name}' is not a class",
|
|
2285
|
+
node.line,
|
|
2286
|
+
hint=f"'{class_name}' is of type {type(class_def).__name__}"
|
|
2287
|
+
)
|
|
2288
|
+
|
|
2289
|
+
# Create new instance
|
|
2290
|
+
instance = CSSLInstance(class_def)
|
|
2291
|
+
|
|
2292
|
+
# Call constructor if defined
|
|
2293
|
+
if class_def.constructor:
|
|
2294
|
+
self._call_method(instance, class_def.constructor, args, kwargs)
|
|
2295
|
+
|
|
2296
|
+
return instance
|
|
2297
|
+
|
|
2298
|
+
def _eval_this_access(self, node: ASTNode) -> Any:
|
|
2299
|
+
"""Evaluate 'this->member' access.
|
|
2300
|
+
|
|
2301
|
+
Returns the value of a member from the current class instance.
|
|
2302
|
+
"""
|
|
2303
|
+
if self._current_instance is None:
|
|
2304
|
+
raise CSSLRuntimeError(
|
|
2305
|
+
"'this' used outside of class method context",
|
|
2306
|
+
node.line if hasattr(node, 'line') else 0,
|
|
2307
|
+
hint="'this->' can only be used inside class methods"
|
|
2308
|
+
)
|
|
2309
|
+
|
|
2310
|
+
member = node.value.get('member')
|
|
2311
|
+
|
|
2312
|
+
# Check if it's a chained access (this->a->b)
|
|
2313
|
+
if 'object' in node.value:
|
|
2314
|
+
# First evaluate the object part
|
|
2315
|
+
obj = self._evaluate(node.value.get('object'))
|
|
2316
|
+
if obj is None:
|
|
2317
|
+
return None
|
|
2318
|
+
if hasattr(obj, member):
|
|
2319
|
+
return getattr(obj, member)
|
|
2320
|
+
if isinstance(obj, dict):
|
|
2321
|
+
return obj.get(member)
|
|
2322
|
+
return None
|
|
2323
|
+
|
|
2324
|
+
# Direct this->member access
|
|
2325
|
+
instance = self._current_instance
|
|
2326
|
+
|
|
2327
|
+
# Check if it's a member variable
|
|
2328
|
+
if instance.has_member(member):
|
|
2329
|
+
return instance.get_member(member)
|
|
2330
|
+
|
|
2331
|
+
# Check if it's a method
|
|
2332
|
+
if instance.has_method(member):
|
|
2333
|
+
# Return a callable that will invoke the method with instance context
|
|
2334
|
+
method_node = instance.get_method(member)
|
|
2335
|
+
return lambda *args, **kwargs: self._call_method(instance, method_node, list(args), kwargs)
|
|
2336
|
+
|
|
2337
|
+
raise CSSLRuntimeError(
|
|
2338
|
+
f"'{instance._class.name}' has no member or method '{member}'",
|
|
2339
|
+
node.line if hasattr(node, 'line') else 0
|
|
2340
|
+
)
|
|
2341
|
+
|
|
2342
|
+
def _call_method(self, instance: CSSLInstance, method_node: ASTNode, args: list, kwargs: dict = None) -> Any:
|
|
2343
|
+
"""Call a method on an instance with 'this' context.
|
|
2344
|
+
|
|
2345
|
+
Sets up the instance as the current 'this' context and executes the method.
|
|
2346
|
+
"""
|
|
2347
|
+
kwargs = kwargs or {}
|
|
2348
|
+
func_info = method_node.value
|
|
2349
|
+
params = func_info.get('params', [])
|
|
2350
|
+
modifiers = func_info.get('modifiers', [])
|
|
2351
|
+
|
|
2352
|
+
# Check for undefined modifier
|
|
2353
|
+
is_undefined = 'undefined' in modifiers
|
|
2354
|
+
|
|
2355
|
+
# Create new scope for method
|
|
2356
|
+
new_scope = Scope(parent=self.scope)
|
|
2357
|
+
|
|
2358
|
+
# Bind parameters
|
|
2359
|
+
for i, param in enumerate(params):
|
|
2360
|
+
param_name = param['name'] if isinstance(param, dict) else param
|
|
2361
|
+
|
|
2362
|
+
if param_name in kwargs:
|
|
2363
|
+
new_scope.set(param_name, kwargs[param_name])
|
|
2364
|
+
elif i < len(args):
|
|
2365
|
+
new_scope.set(param_name, args[i])
|
|
2366
|
+
else:
|
|
2367
|
+
new_scope.set(param_name, None)
|
|
2368
|
+
|
|
2369
|
+
# Save current state
|
|
2370
|
+
old_scope = self.scope
|
|
2371
|
+
old_instance = self._current_instance
|
|
2372
|
+
|
|
2373
|
+
# Set up method context
|
|
2374
|
+
self.scope = new_scope
|
|
2375
|
+
self._current_instance = instance
|
|
2376
|
+
|
|
2377
|
+
try:
|
|
2378
|
+
for child in method_node.children:
|
|
2379
|
+
if not self._running:
|
|
2380
|
+
break
|
|
2381
|
+
self._execute_node(child)
|
|
2382
|
+
except CSSLReturn as ret:
|
|
2383
|
+
return ret.value
|
|
2384
|
+
except Exception as e:
|
|
2385
|
+
if is_undefined:
|
|
2386
|
+
return None
|
|
2387
|
+
raise
|
|
2388
|
+
finally:
|
|
2389
|
+
# Restore previous state
|
|
2390
|
+
self.scope = old_scope
|
|
2391
|
+
self._current_instance = old_instance
|
|
2392
|
+
|
|
2393
|
+
return None
|
|
2394
|
+
|
|
2139
2395
|
def _eval_member_access(self, node: ASTNode) -> Any:
|
|
2140
2396
|
"""Evaluate member access"""
|
|
2141
2397
|
obj = self._evaluate(node.value.get('object'))
|
|
@@ -2149,6 +2405,17 @@ class CSSLRuntime:
|
|
|
2149
2405
|
if isinstance(obj, Parameter) and member == 'return':
|
|
2150
2406
|
member = 'return_'
|
|
2151
2407
|
|
|
2408
|
+
# === CSSL CLASS INSTANCE METHODS ===
|
|
2409
|
+
if isinstance(obj, CSSLInstance):
|
|
2410
|
+
# Check for member variable
|
|
2411
|
+
if obj.has_member(member):
|
|
2412
|
+
return obj.get_member(member)
|
|
2413
|
+
# Check for method
|
|
2414
|
+
if obj.has_method(member):
|
|
2415
|
+
method_node = obj.get_method(member)
|
|
2416
|
+
return lambda *args, **kwargs: self._call_method(obj, method_node, list(args), kwargs)
|
|
2417
|
+
raise CSSLRuntimeError(f"'{obj._class.name}' has no member or method '{member}'")
|
|
2418
|
+
|
|
2152
2419
|
# === STRING METHODS ===
|
|
2153
2420
|
if isinstance(obj, str):
|
|
2154
2421
|
string_methods = self._get_string_method(obj, member)
|
|
@@ -2382,6 +2649,11 @@ class CSSLRuntime:
|
|
|
2382
2649
|
if obj is None:
|
|
2383
2650
|
return
|
|
2384
2651
|
|
|
2652
|
+
# Check for CSSLInstance - use set_member method
|
|
2653
|
+
if isinstance(obj, CSSLInstance):
|
|
2654
|
+
obj.set_member(member, value)
|
|
2655
|
+
return
|
|
2656
|
+
|
|
2385
2657
|
# Check for SharedObjectProxy - directly access underlying object
|
|
2386
2658
|
# This is more robust than relying on the proxy's __setattr__
|
|
2387
2659
|
if hasattr(obj, '_direct_object') and hasattr(obj, '_name'):
|
|
@@ -1281,10 +1281,232 @@ def create_dictionary(key_type: str = 'dynamic', value_type: str = 'dynamic') ->
|
|
|
1281
1281
|
return Dictionary(key_type, value_type)
|
|
1282
1282
|
|
|
1283
1283
|
|
|
1284
|
+
class Map(dict):
|
|
1285
|
+
"""C++ style map container with ordered key-value pairs.
|
|
1286
|
+
|
|
1287
|
+
Similar to Dictionary but with C++ map semantics.
|
|
1288
|
+
Keys are maintained in sorted order.
|
|
1289
|
+
|
|
1290
|
+
Usage:
|
|
1291
|
+
map<string, int> ages;
|
|
1292
|
+
ages.insert("Alice", 30);
|
|
1293
|
+
ages.find("Alice");
|
|
1294
|
+
ages.erase("Alice");
|
|
1295
|
+
"""
|
|
1296
|
+
|
|
1297
|
+
def __init__(self, key_type: str = 'dynamic', value_type: str = 'dynamic'):
|
|
1298
|
+
super().__init__()
|
|
1299
|
+
self._key_type = key_type
|
|
1300
|
+
self._value_type = value_type
|
|
1301
|
+
|
|
1302
|
+
def insert(self, key: Any, value: Any) -> 'Map':
|
|
1303
|
+
"""Insert key-value pair (C++ style)"""
|
|
1304
|
+
self[key] = value
|
|
1305
|
+
return self
|
|
1306
|
+
|
|
1307
|
+
def find(self, key: Any) -> Optional[Any]:
|
|
1308
|
+
"""Find value by key, returns None if not found (C++ style)"""
|
|
1309
|
+
return self.get(key, None)
|
|
1310
|
+
|
|
1311
|
+
def erase(self, key: Any) -> bool:
|
|
1312
|
+
"""Erase key-value pair, returns True if existed"""
|
|
1313
|
+
if key in self:
|
|
1314
|
+
del self[key]
|
|
1315
|
+
return True
|
|
1316
|
+
return False
|
|
1317
|
+
|
|
1318
|
+
def contains(self, key: Any) -> bool:
|
|
1319
|
+
"""Check if key exists (C++20 style)"""
|
|
1320
|
+
return key in self
|
|
1321
|
+
|
|
1322
|
+
def count(self, key: Any) -> int:
|
|
1323
|
+
"""Return 1 if key exists, 0 otherwise (C++ style)"""
|
|
1324
|
+
return 1 if key in self else 0
|
|
1325
|
+
|
|
1326
|
+
def size(self) -> int:
|
|
1327
|
+
"""Return map size"""
|
|
1328
|
+
return len(self)
|
|
1329
|
+
|
|
1330
|
+
def empty(self) -> bool:
|
|
1331
|
+
"""Check if map is empty"""
|
|
1332
|
+
return len(self) == 0
|
|
1333
|
+
|
|
1334
|
+
def at(self, key: Any) -> Any:
|
|
1335
|
+
"""Get value at key, raises error if not found (C++ style)"""
|
|
1336
|
+
if key not in self:
|
|
1337
|
+
raise KeyError(f"Key '{key}' not found in map")
|
|
1338
|
+
return self[key]
|
|
1339
|
+
|
|
1340
|
+
def begin(self) -> Optional[tuple]:
|
|
1341
|
+
"""Return first key-value pair"""
|
|
1342
|
+
if len(self) == 0:
|
|
1343
|
+
return None
|
|
1344
|
+
first_key = next(iter(self))
|
|
1345
|
+
return (first_key, self[first_key])
|
|
1346
|
+
|
|
1347
|
+
def end(self) -> Optional[tuple]:
|
|
1348
|
+
"""Return last key-value pair"""
|
|
1349
|
+
if len(self) == 0:
|
|
1350
|
+
return None
|
|
1351
|
+
last_key = list(self.keys())[-1]
|
|
1352
|
+
return (last_key, self[last_key])
|
|
1353
|
+
|
|
1354
|
+
def lower_bound(self, key: Any) -> Optional[Any]:
|
|
1355
|
+
"""Find first key >= given key (for sorted keys)"""
|
|
1356
|
+
sorted_keys = sorted(self.keys())
|
|
1357
|
+
for k in sorted_keys:
|
|
1358
|
+
if k >= key:
|
|
1359
|
+
return k
|
|
1360
|
+
return None
|
|
1361
|
+
|
|
1362
|
+
def upper_bound(self, key: Any) -> Optional[Any]:
|
|
1363
|
+
"""Find first key > given key (for sorted keys)"""
|
|
1364
|
+
sorted_keys = sorted(self.keys())
|
|
1365
|
+
for k in sorted_keys:
|
|
1366
|
+
if k > key:
|
|
1367
|
+
return k
|
|
1368
|
+
return None
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
def create_map(key_type: str = 'dynamic', value_type: str = 'dynamic') -> Map:
|
|
1372
|
+
"""Create a Map object"""
|
|
1373
|
+
return Map(key_type, value_type)
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
class CSSLClass:
|
|
1377
|
+
"""Represents a CSSL class definition.
|
|
1378
|
+
|
|
1379
|
+
Stores class name, member variables, methods, and constructor.
|
|
1380
|
+
Used by the runtime to instantiate CSSLInstance objects.
|
|
1381
|
+
"""
|
|
1382
|
+
|
|
1383
|
+
def __init__(self, name: str, members: Dict[str, Any] = None,
|
|
1384
|
+
methods: Dict[str, Any] = None, constructor: Any = None):
|
|
1385
|
+
self.name = name
|
|
1386
|
+
self.members = members or {} # Default member values/types
|
|
1387
|
+
self.methods = methods or {} # Method AST nodes
|
|
1388
|
+
self.constructor = constructor # Constructor AST node
|
|
1389
|
+
|
|
1390
|
+
def __repr__(self):
|
|
1391
|
+
return f"<CSSLClass '{self.name}' with {len(self.methods)} methods>"
|
|
1392
|
+
|
|
1393
|
+
|
|
1394
|
+
class CSSLInstance:
|
|
1395
|
+
"""Represents an instance of a CSSL class.
|
|
1396
|
+
|
|
1397
|
+
Holds instance member values and provides access to class methods.
|
|
1398
|
+
Supports this-> member access pattern.
|
|
1399
|
+
"""
|
|
1400
|
+
|
|
1401
|
+
def __init__(self, class_def: CSSLClass):
|
|
1402
|
+
self._class = class_def
|
|
1403
|
+
self._members: Dict[str, Any] = {}
|
|
1404
|
+
# Initialize members with defaults from class definition
|
|
1405
|
+
for name, default in class_def.members.items():
|
|
1406
|
+
if isinstance(default, dict):
|
|
1407
|
+
# Type declaration with optional default
|
|
1408
|
+
member_type = default.get('type')
|
|
1409
|
+
member_default = default.get('default')
|
|
1410
|
+
|
|
1411
|
+
if member_default is not None:
|
|
1412
|
+
self._members[name] = member_default
|
|
1413
|
+
elif member_type:
|
|
1414
|
+
# Create instance of container types
|
|
1415
|
+
self._members[name] = self._create_default_for_type(member_type)
|
|
1416
|
+
else:
|
|
1417
|
+
self._members[name] = None
|
|
1418
|
+
else:
|
|
1419
|
+
self._members[name] = default
|
|
1420
|
+
|
|
1421
|
+
def _create_default_for_type(self, type_name: str) -> Any:
|
|
1422
|
+
"""Create a default value for a given type name."""
|
|
1423
|
+
# Container types
|
|
1424
|
+
if type_name == 'map':
|
|
1425
|
+
return Map()
|
|
1426
|
+
elif type_name in ('stack',):
|
|
1427
|
+
return Stack()
|
|
1428
|
+
elif type_name in ('vector',):
|
|
1429
|
+
return Vector()
|
|
1430
|
+
elif type_name in ('array',):
|
|
1431
|
+
return Array()
|
|
1432
|
+
elif type_name in ('list',):
|
|
1433
|
+
return List()
|
|
1434
|
+
elif type_name in ('dictionary', 'dict'):
|
|
1435
|
+
return Dictionary()
|
|
1436
|
+
elif type_name == 'datastruct':
|
|
1437
|
+
return DataStruct()
|
|
1438
|
+
elif type_name == 'dataspace':
|
|
1439
|
+
return DataSpace()
|
|
1440
|
+
elif type_name == 'shuffled':
|
|
1441
|
+
return Shuffled()
|
|
1442
|
+
elif type_name == 'iterator':
|
|
1443
|
+
return Iterator()
|
|
1444
|
+
elif type_name == 'combo':
|
|
1445
|
+
return Combo()
|
|
1446
|
+
# Primitive types
|
|
1447
|
+
elif type_name == 'int':
|
|
1448
|
+
return 0
|
|
1449
|
+
elif type_name == 'float':
|
|
1450
|
+
return 0.0
|
|
1451
|
+
elif type_name == 'string':
|
|
1452
|
+
return ""
|
|
1453
|
+
elif type_name == 'bool':
|
|
1454
|
+
return False
|
|
1455
|
+
elif type_name == 'json':
|
|
1456
|
+
return {}
|
|
1457
|
+
return None
|
|
1458
|
+
|
|
1459
|
+
def get_member(self, name: str) -> Any:
|
|
1460
|
+
"""Get member value by name"""
|
|
1461
|
+
if name in self._members:
|
|
1462
|
+
return self._members[name]
|
|
1463
|
+
raise AttributeError(f"'{self._class.name}' has no member '{name}'")
|
|
1464
|
+
|
|
1465
|
+
def set_member(self, name: str, value: Any) -> None:
|
|
1466
|
+
"""Set member value by name"""
|
|
1467
|
+
self._members[name] = value
|
|
1468
|
+
|
|
1469
|
+
def has_member(self, name: str) -> bool:
|
|
1470
|
+
"""Check if member exists"""
|
|
1471
|
+
return name in self._members
|
|
1472
|
+
|
|
1473
|
+
def get_method(self, name: str) -> Any:
|
|
1474
|
+
"""Get method AST node by name"""
|
|
1475
|
+
if name in self._class.methods:
|
|
1476
|
+
return self._class.methods[name]
|
|
1477
|
+
raise AttributeError(f"'{self._class.name}' has no method '{name}'")
|
|
1478
|
+
|
|
1479
|
+
def has_method(self, name: str) -> bool:
|
|
1480
|
+
"""Check if method exists"""
|
|
1481
|
+
return name in self._class.methods
|
|
1482
|
+
|
|
1483
|
+
def __getattr__(self, name: str) -> Any:
|
|
1484
|
+
"""Allow direct attribute access for members"""
|
|
1485
|
+
if name.startswith('_'):
|
|
1486
|
+
raise AttributeError(name)
|
|
1487
|
+
if name in self._members:
|
|
1488
|
+
return self._members[name]
|
|
1489
|
+
raise AttributeError(f"'{self._class.name}' has no member '{name}'")
|
|
1490
|
+
|
|
1491
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
1492
|
+
"""Allow direct attribute setting for members"""
|
|
1493
|
+
if name.startswith('_'):
|
|
1494
|
+
object.__setattr__(self, name, value)
|
|
1495
|
+
else:
|
|
1496
|
+
if hasattr(self, '_members'):
|
|
1497
|
+
self._members[name] = value
|
|
1498
|
+
else:
|
|
1499
|
+
object.__setattr__(self, name, value)
|
|
1500
|
+
|
|
1501
|
+
def __repr__(self):
|
|
1502
|
+
return f"<CSSLInstance of '{self._class.name}'>"
|
|
1503
|
+
|
|
1504
|
+
|
|
1284
1505
|
__all__ = [
|
|
1285
1506
|
'DataStruct', 'Shuffled', 'Iterator', 'Combo', 'DataSpace', 'OpenQuote',
|
|
1286
|
-
'OpenFind', 'Parameter', 'Stack', 'Vector', 'Array', 'List', 'Dictionary',
|
|
1507
|
+
'OpenFind', 'Parameter', 'Stack', 'Vector', 'Array', 'List', 'Dictionary', 'Map',
|
|
1508
|
+
'CSSLClass', 'CSSLInstance',
|
|
1287
1509
|
'create_datastruct', 'create_shuffled', 'create_iterator',
|
|
1288
1510
|
'create_combo', 'create_dataspace', 'create_openquote', 'create_parameter',
|
|
1289
|
-
'create_stack', 'create_vector', 'create_array', 'create_list', 'create_dictionary'
|
|
1511
|
+
'create_stack', 'create_vector', 'create_array', 'create_list', 'create_dictionary', 'create_map'
|
|
1290
1512
|
]
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cssl",
|
|
3
3
|
"displayName": "CSSL - CSO Service Script Language",
|
|
4
|
-
"description": "
|
|
5
|
-
"version": "1.
|
|
4
|
+
"description": "Professional syntax highlighting, snippets, and language support for CSSL scripts (.cssl, .cssl-pl, .cssl-mod)",
|
|
5
|
+
"version": "1.1.0",
|
|
6
6
|
"publisher": "IncludeCPP",
|
|
7
|
+
"icon": "images/cssl-icon.png",
|
|
7
8
|
"engines": {
|
|
8
9
|
"vscode": "^1.60.0"
|
|
9
10
|
},
|
|
10
11
|
"categories": [
|
|
11
|
-
"Programming Languages"
|
|
12
|
+
"Programming Languages",
|
|
13
|
+
"Snippets"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"cssl",
|
|
17
|
+
"cso",
|
|
18
|
+
"script",
|
|
19
|
+
"includecpp",
|
|
20
|
+
"c++",
|
|
21
|
+
"python"
|
|
12
22
|
],
|
|
13
23
|
"contributes": {
|
|
14
24
|
"languages": [
|
|
@@ -16,7 +26,11 @@
|
|
|
16
26
|
"id": "cssl",
|
|
17
27
|
"aliases": ["CSSL", "cssl", "CSO Service Script"],
|
|
18
28
|
"extensions": [".cssl", ".cssl-pl", ".cssl-mod"],
|
|
19
|
-
"configuration": "./language-configuration.json"
|
|
29
|
+
"configuration": "./language-configuration.json",
|
|
30
|
+
"icon": {
|
|
31
|
+
"light": "./images/cssl-icon.png",
|
|
32
|
+
"dark": "./images/cssl-icon.png"
|
|
33
|
+
}
|
|
20
34
|
}
|
|
21
35
|
],
|
|
22
36
|
"grammars": [
|
|
@@ -25,6 +39,12 @@
|
|
|
25
39
|
"scopeName": "source.cssl",
|
|
26
40
|
"path": "./syntaxes/cssl.tmLanguage.json"
|
|
27
41
|
}
|
|
42
|
+
],
|
|
43
|
+
"snippets": [
|
|
44
|
+
{
|
|
45
|
+
"language": "cssl",
|
|
46
|
+
"path": "./snippets/cssl.snippets.json"
|
|
47
|
+
}
|
|
28
48
|
]
|
|
29
49
|
}
|
|
30
50
|
}
|