zexus 1.6.2
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.
- package/LICENSE +0 -0
- package/README.md +2513 -0
- package/bin/zexus +2 -0
- package/bin/zpics +2 -0
- package/bin/zpm +2 -0
- package/bin/zx +2 -0
- package/bin/zx-deploy +2 -0
- package/bin/zx-dev +2 -0
- package/bin/zx-run +2 -0
- package/package.json +66 -0
- package/scripts/README.md +24 -0
- package/scripts/postinstall.js +44 -0
- package/shared_config.json +24 -0
- package/src/README.md +1525 -0
- package/src/tests/run_zexus_tests.py +117 -0
- package/src/tests/test_all_phases.zx +346 -0
- package/src/tests/test_blockchain_features.zx +306 -0
- package/src/tests/test_complexity_features.zx +321 -0
- package/src/tests/test_core_integration.py +185 -0
- package/src/tests/test_phase10_ecosystem.zx +177 -0
- package/src/tests/test_phase1_modifiers.zx +87 -0
- package/src/tests/test_phase2_plugins.zx +80 -0
- package/src/tests/test_phase3_security.zx +97 -0
- package/src/tests/test_phase4_vfs.zx +116 -0
- package/src/tests/test_phase5_types.zx +117 -0
- package/src/tests/test_phase6_metaprogramming.zx +125 -0
- package/src/tests/test_phase7_optimization.zx +132 -0
- package/src/tests/test_phase9_advanced_types.zx +157 -0
- package/src/tests/test_security_features.py +419 -0
- package/src/tests/test_security_features.zx +276 -0
- package/src/tests/test_simple_zx.zx +1 -0
- package/src/tests/test_verification_simple.zx +69 -0
- package/src/zexus/__init__.py +28 -0
- package/src/zexus/__main__.py +5 -0
- package/src/zexus/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/advanced_types.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/builtin_modules.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/capability_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/complexity_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/concurrency_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/config.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/dependency_injection.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/ecosystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/environment.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/error_reporter.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/hybrid_orchestrator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/metaprogramming.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/module_cache.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/object.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/optimization.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/plugin_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/policy_engine.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/security.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/stdlib_integration.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/strategy_recovery.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/syntax_validator.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/type_system.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/virtual_filesystem.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/__pycache__/zexus_token.cpython-312.pyc +0 -0
- package/src/zexus/advanced_types.py +401 -0
- package/src/zexus/blockchain/__init__.py +40 -0
- package/src/zexus/blockchain/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/crypto.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/ledger.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/__pycache__/transaction.cpython-312.pyc +0 -0
- package/src/zexus/blockchain/crypto.py +463 -0
- package/src/zexus/blockchain/ledger.py +255 -0
- package/src/zexus/blockchain/transaction.py +267 -0
- package/src/zexus/builtin_modules.py +284 -0
- package/src/zexus/builtin_plugins.py +317 -0
- package/src/zexus/capability_system.py +372 -0
- package/src/zexus/cli/__init__.py +2 -0
- package/src/zexus/cli/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/cli/__pycache__/main.cpython-312.pyc +0 -0
- package/src/zexus/cli/main.py +707 -0
- package/src/zexus/cli/zpm.py +203 -0
- package/src/zexus/compare_interpreter_compiler.py +146 -0
- package/src/zexus/compiler/__init__.py +169 -0
- package/src/zexus/compiler/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/lexer.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/compiler/__pycache__/zexus_ast.cpython-312.pyc +0 -0
- package/src/zexus/compiler/bytecode.py +266 -0
- package/src/zexus/compiler/compat_runtime.py +277 -0
- package/src/zexus/compiler/lexer.py +257 -0
- package/src/zexus/compiler/parser.py +779 -0
- package/src/zexus/compiler/semantic.py +118 -0
- package/src/zexus/compiler/zexus_ast.py +454 -0
- package/src/zexus/complexity_system.py +575 -0
- package/src/zexus/concurrency_system.py +493 -0
- package/src/zexus/config.py +201 -0
- package/src/zexus/crypto_bridge.py +19 -0
- package/src/zexus/dependency_injection.py +423 -0
- package/src/zexus/ecosystem.py +434 -0
- package/src/zexus/environment.py +101 -0
- package/src/zexus/environment_manager.py +119 -0
- package/src/zexus/error_reporter.py +314 -0
- package/src/zexus/evaluator/__init__.py +12 -0
- package/src/zexus/evaluator/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/bytecode_compiler.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/core.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/expressions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/functions.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/integration.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/statements.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/__pycache__/utils.cpython-312.pyc +0 -0
- package/src/zexus/evaluator/bytecode_compiler.py +700 -0
- package/src/zexus/evaluator/core.py +891 -0
- package/src/zexus/evaluator/expressions.py +827 -0
- package/src/zexus/evaluator/functions.py +3989 -0
- package/src/zexus/evaluator/integration.py +396 -0
- package/src/zexus/evaluator/statements.py +4303 -0
- package/src/zexus/evaluator/utils.py +126 -0
- package/src/zexus/evaluator_original.py +2041 -0
- package/src/zexus/external_bridge.py +16 -0
- package/src/zexus/find_affected_imports.sh +155 -0
- package/src/zexus/hybrid_orchestrator.py +152 -0
- package/src/zexus/input_validation.py +259 -0
- package/src/zexus/lexer.py +571 -0
- package/src/zexus/logging.py +89 -0
- package/src/zexus/lsp/__init__.py +9 -0
- package/src/zexus/lsp/completion_provider.py +207 -0
- package/src/zexus/lsp/definition_provider.py +22 -0
- package/src/zexus/lsp/hover_provider.py +71 -0
- package/src/zexus/lsp/server.py +269 -0
- package/src/zexus/lsp/symbol_provider.py +31 -0
- package/src/zexus/metaprogramming.py +321 -0
- package/src/zexus/module_cache.py +89 -0
- package/src/zexus/module_manager.py +107 -0
- package/src/zexus/object.py +973 -0
- package/src/zexus/optimization.py +424 -0
- package/src/zexus/parser/__init__.py +31 -0
- package/src/zexus/parser/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/parser.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_context.cpython-312.pyc +0 -0
- package/src/zexus/parser/__pycache__/strategy_structural.cpython-312.pyc +0 -0
- package/src/zexus/parser/integration.py +86 -0
- package/src/zexus/parser/parser.py +3977 -0
- package/src/zexus/parser/strategy_context.py +7254 -0
- package/src/zexus/parser/strategy_structural.py +1033 -0
- package/src/zexus/persistence.py +391 -0
- package/src/zexus/plugin_system.py +290 -0
- package/src/zexus/policy_engine.py +365 -0
- package/src/zexus/profiler/__init__.py +5 -0
- package/src/zexus/profiler/profiler.py +233 -0
- package/src/zexus/purity_system.py +398 -0
- package/src/zexus/runtime/__init__.py +20 -0
- package/src/zexus/runtime/async_runtime.py +324 -0
- package/src/zexus/search_old_imports.sh +65 -0
- package/src/zexus/security.py +1407 -0
- package/src/zexus/stack_trace.py +233 -0
- package/src/zexus/stdlib/__init__.py +27 -0
- package/src/zexus/stdlib/blockchain.py +341 -0
- package/src/zexus/stdlib/compression.py +167 -0
- package/src/zexus/stdlib/crypto.py +124 -0
- package/src/zexus/stdlib/datetime.py +163 -0
- package/src/zexus/stdlib/db_mongo.py +199 -0
- package/src/zexus/stdlib/db_mysql.py +162 -0
- package/src/zexus/stdlib/db_postgres.py +163 -0
- package/src/zexus/stdlib/db_sqlite.py +133 -0
- package/src/zexus/stdlib/encoding.py +230 -0
- package/src/zexus/stdlib/fs.py +195 -0
- package/src/zexus/stdlib/http.py +219 -0
- package/src/zexus/stdlib/http_server.py +248 -0
- package/src/zexus/stdlib/json_module.py +61 -0
- package/src/zexus/stdlib/math.py +360 -0
- package/src/zexus/stdlib/os_module.py +265 -0
- package/src/zexus/stdlib/regex.py +148 -0
- package/src/zexus/stdlib/sockets.py +253 -0
- package/src/zexus/stdlib/test_framework.zx +208 -0
- package/src/zexus/stdlib/test_runner.zx +119 -0
- package/src/zexus/stdlib_integration.py +341 -0
- package/src/zexus/strategy_recovery.py +256 -0
- package/src/zexus/syntax_validator.py +356 -0
- package/src/zexus/testing/zpics.py +407 -0
- package/src/zexus/testing/zpics_runtime.py +369 -0
- package/src/zexus/type_system.py +374 -0
- package/src/zexus/validation_system.py +569 -0
- package/src/zexus/virtual_filesystem.py +355 -0
- package/src/zexus/vm/__init__.py +8 -0
- package/src/zexus/vm/__pycache__/__init__.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/async_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/bytecode.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/cache.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/jit.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_manager.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/memory_pool.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/parallel_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/peephole_optimizer.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/profiler.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_allocator.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/register_vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/ssa_converter.cpython-312.pyc +0 -0
- package/src/zexus/vm/__pycache__/vm.cpython-312.pyc +0 -0
- package/src/zexus/vm/async_optimizer.py +420 -0
- package/src/zexus/vm/bytecode.py +428 -0
- package/src/zexus/vm/bytecode_converter.py +297 -0
- package/src/zexus/vm/cache.py +532 -0
- package/src/zexus/vm/jit.py +720 -0
- package/src/zexus/vm/memory_manager.py +520 -0
- package/src/zexus/vm/memory_pool.py +511 -0
- package/src/zexus/vm/optimizer.py +478 -0
- package/src/zexus/vm/parallel_vm.py +899 -0
- package/src/zexus/vm/peephole_optimizer.py +452 -0
- package/src/zexus/vm/profiler.py +527 -0
- package/src/zexus/vm/register_allocator.py +462 -0
- package/src/zexus/vm/register_vm.py +520 -0
- package/src/zexus/vm/ssa_converter.py +757 -0
- package/src/zexus/vm/vm.py +1392 -0
- package/src/zexus/zexus_ast.py +1782 -0
- package/src/zexus/zexus_token.py +253 -0
- package/src/zexus/zpm/__init__.py +15 -0
- package/src/zexus/zpm/installer.py +116 -0
- package/src/zexus/zpm/package_manager.py +208 -0
- package/src/zexus/zpm/publisher.py +98 -0
- package/src/zexus/zpm/registry.py +110 -0
- package/src/zexus.egg-info/PKG-INFO +2235 -0
- package/src/zexus.egg-info/SOURCES.txt +876 -0
- package/src/zexus.egg-info/dependency_links.txt +1 -0
- package/src/zexus.egg-info/entry_points.txt +3 -0
- package/src/zexus.egg-info/not-zip-safe +1 -0
- package/src/zexus.egg-info/requires.txt +14 -0
- package/src/zexus.egg-info/top_level.txt +2 -0
- package/zexus.json +14 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unified type system for Zexus.
|
|
3
|
+
|
|
4
|
+
Provides runtime type checking, type annotations, and custom type definitions.
|
|
5
|
+
Supports basic types, compound types, and user-defined types.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Dict, List, Optional, Callable, Union, Set, Tuple
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from enum import Enum
|
|
11
|
+
import re
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BaseType(Enum):
|
|
15
|
+
"""Base type constants."""
|
|
16
|
+
NONE = "none"
|
|
17
|
+
BOOL = "bool"
|
|
18
|
+
INT = "int"
|
|
19
|
+
FLOAT = "float"
|
|
20
|
+
STRING = "string"
|
|
21
|
+
ARRAY = "array"
|
|
22
|
+
OBJECT = "object"
|
|
23
|
+
ACTION = "action"
|
|
24
|
+
ANY = "any"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class TypeSpec:
|
|
29
|
+
"""Type specification for values."""
|
|
30
|
+
base_type: Union[BaseType, str]
|
|
31
|
+
nullable: bool = False
|
|
32
|
+
array_of: Optional['TypeSpec'] = None
|
|
33
|
+
object_schema: Optional[Dict[str, 'TypeSpec']] = None
|
|
34
|
+
custom_validator: Optional[Callable[[Any], bool]] = None
|
|
35
|
+
|
|
36
|
+
def __str__(self) -> str:
|
|
37
|
+
"""String representation of type."""
|
|
38
|
+
type_str = self.base_type.value if isinstance(self.base_type, BaseType) else self.base_type
|
|
39
|
+
|
|
40
|
+
if self.array_of:
|
|
41
|
+
type_str = f"[{self.array_of}]"
|
|
42
|
+
|
|
43
|
+
if self.object_schema:
|
|
44
|
+
fields = ", ".join(f"{k}:{v}" for k, v in self.object_schema.items())
|
|
45
|
+
type_str = f"{{{fields}}}"
|
|
46
|
+
|
|
47
|
+
if self.nullable:
|
|
48
|
+
type_str = f"{type_str}?"
|
|
49
|
+
|
|
50
|
+
return type_str
|
|
51
|
+
|
|
52
|
+
def is_compatible_with(self, other: 'TypeSpec') -> bool:
|
|
53
|
+
"""Check if this type is compatible with another."""
|
|
54
|
+
if other.base_type == BaseType.ANY:
|
|
55
|
+
return True
|
|
56
|
+
|
|
57
|
+
if self.base_type == BaseType.ANY:
|
|
58
|
+
return True
|
|
59
|
+
|
|
60
|
+
if self.base_type != other.base_type:
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
if self.nullable and not other.nullable:
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
return True
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class TypeChecker:
|
|
70
|
+
"""
|
|
71
|
+
Checks values against type specifications.
|
|
72
|
+
|
|
73
|
+
Supports both built-in types and custom validators.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __init__(self):
|
|
77
|
+
"""Initialize type checker."""
|
|
78
|
+
self.custom_types: Dict[str, TypeSpec] = {}
|
|
79
|
+
self.validators: Dict[str, Callable[[Any], bool]] = {}
|
|
80
|
+
|
|
81
|
+
def register_type(self, name: str, type_spec: TypeSpec):
|
|
82
|
+
"""Register a custom type."""
|
|
83
|
+
self.custom_types[name] = type_spec
|
|
84
|
+
|
|
85
|
+
def register_validator(self, type_name: str, validator: Callable[[Any], bool]):
|
|
86
|
+
"""Register a custom validator function."""
|
|
87
|
+
self.validators[type_name] = validator
|
|
88
|
+
|
|
89
|
+
def get_type(self, name: str) -> Optional[TypeSpec]:
|
|
90
|
+
"""Get a registered type by name."""
|
|
91
|
+
return self.custom_types.get(name)
|
|
92
|
+
|
|
93
|
+
def check_type(self, value: Any, type_spec: TypeSpec) -> Tuple[bool, str]:
|
|
94
|
+
"""
|
|
95
|
+
Check if value matches type specification.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
(matches: bool, reason: str)
|
|
99
|
+
"""
|
|
100
|
+
# Handle None/null values
|
|
101
|
+
if value is None:
|
|
102
|
+
if type_spec.nullable:
|
|
103
|
+
return True, "Value is null (allowed)"
|
|
104
|
+
else:
|
|
105
|
+
return False, f"Value is null but {type_spec} is not nullable"
|
|
106
|
+
|
|
107
|
+
# Handle custom validators
|
|
108
|
+
if type_spec.custom_validator:
|
|
109
|
+
try:
|
|
110
|
+
if type_spec.custom_validator(value):
|
|
111
|
+
return True, "Value passes custom validator"
|
|
112
|
+
else:
|
|
113
|
+
return False, f"Value fails custom validator for {type_spec}"
|
|
114
|
+
except Exception as e:
|
|
115
|
+
return False, f"Error in custom validator: {e}"
|
|
116
|
+
|
|
117
|
+
# Handle array types
|
|
118
|
+
if type_spec.array_of:
|
|
119
|
+
if not isinstance(value, list):
|
|
120
|
+
return False, f"Expected array, got {type(value).__name__}"
|
|
121
|
+
|
|
122
|
+
for i, item in enumerate(value):
|
|
123
|
+
matches, reason = self.check_type(item, type_spec.array_of)
|
|
124
|
+
if not matches:
|
|
125
|
+
return False, f"Item {i} in array: {reason}"
|
|
126
|
+
|
|
127
|
+
return True, "All array items match type"
|
|
128
|
+
|
|
129
|
+
# Handle object/dict types
|
|
130
|
+
if type_spec.object_schema:
|
|
131
|
+
if not isinstance(value, dict):
|
|
132
|
+
return False, f"Expected object, got {type(value).__name__}"
|
|
133
|
+
|
|
134
|
+
# Check required fields
|
|
135
|
+
for field_name, field_type in type_spec.object_schema.items():
|
|
136
|
+
if field_name not in value:
|
|
137
|
+
return False, f"Missing required field '{field_name}' of type {field_type}"
|
|
138
|
+
|
|
139
|
+
matches, reason = self.check_type(value[field_name], field_type)
|
|
140
|
+
if not matches:
|
|
141
|
+
return False, f"Field '{field_name}': {reason}"
|
|
142
|
+
|
|
143
|
+
return True, "Object matches schema"
|
|
144
|
+
|
|
145
|
+
# Check base types
|
|
146
|
+
type_name = type_spec.base_type.value if isinstance(type_spec.base_type, BaseType) else type_spec.base_type
|
|
147
|
+
return self._check_base_type(value, type_name)
|
|
148
|
+
|
|
149
|
+
def _check_base_type(self, value: Any, type_name: str) -> Tuple[bool, str]:
|
|
150
|
+
"""Check value against base type."""
|
|
151
|
+
if type_name == "any":
|
|
152
|
+
return True, "Type is 'any'"
|
|
153
|
+
|
|
154
|
+
if type_name == "bool":
|
|
155
|
+
if isinstance(value, bool):
|
|
156
|
+
return True, f"Value is bool"
|
|
157
|
+
return False, f"Expected bool, got {type(value).__name__}"
|
|
158
|
+
|
|
159
|
+
if type_name == "int":
|
|
160
|
+
if isinstance(value, int) and not isinstance(value, bool):
|
|
161
|
+
return True, f"Value is int"
|
|
162
|
+
return False, f"Expected int, got {type(value).__name__}"
|
|
163
|
+
|
|
164
|
+
if type_name == "float":
|
|
165
|
+
if isinstance(value, (int, float)) and not isinstance(value, bool):
|
|
166
|
+
return True, f"Value is numeric"
|
|
167
|
+
return False, f"Expected float, got {type(value).__name__}"
|
|
168
|
+
|
|
169
|
+
if type_name == "string":
|
|
170
|
+
if isinstance(value, str):
|
|
171
|
+
return True, f"Value is string"
|
|
172
|
+
return False, f"Expected string, got {type(value).__name__}"
|
|
173
|
+
|
|
174
|
+
if type_name == "array":
|
|
175
|
+
if isinstance(value, list):
|
|
176
|
+
return True, f"Value is array"
|
|
177
|
+
return False, f"Expected array, got {type(value).__name__}"
|
|
178
|
+
|
|
179
|
+
if type_name == "object":
|
|
180
|
+
if isinstance(value, dict):
|
|
181
|
+
return True, f"Value is object"
|
|
182
|
+
return False, f"Expected object, got {type(value).__name__}"
|
|
183
|
+
|
|
184
|
+
if type_name == "action":
|
|
185
|
+
# Actions are callable-like objects
|
|
186
|
+
return callable(value), f"Value is {'action' if callable(value) else 'not action'}"
|
|
187
|
+
|
|
188
|
+
# Unknown type
|
|
189
|
+
return False, f"Unknown type: {type_name}"
|
|
190
|
+
|
|
191
|
+
def require_type(self, value: Any, type_spec: TypeSpec, context: str = "") -> bool:
|
|
192
|
+
"""
|
|
193
|
+
Require that value matches type. Raises TypeError if not.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
value: Value to check
|
|
197
|
+
type_spec: Expected type
|
|
198
|
+
context: Context description for error message
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
True if value matches type
|
|
202
|
+
|
|
203
|
+
Raises:
|
|
204
|
+
TypeError: If type check fails
|
|
205
|
+
"""
|
|
206
|
+
matches, reason = self.check_type(value, type_spec)
|
|
207
|
+
if not matches:
|
|
208
|
+
error_msg = f"Type mismatch{f' in {context}' if context else ''}: {reason}"
|
|
209
|
+
raise TypeError(error_msg)
|
|
210
|
+
return True
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class TypeInferencer:
|
|
214
|
+
"""
|
|
215
|
+
Infers types of values at runtime.
|
|
216
|
+
|
|
217
|
+
Used when type annotations are not provided.
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
@staticmethod
|
|
221
|
+
def infer_type(value: Any) -> TypeSpec:
|
|
222
|
+
"""Infer the type of a value."""
|
|
223
|
+
if value is None:
|
|
224
|
+
return TypeSpec(BaseType.NONE)
|
|
225
|
+
|
|
226
|
+
if isinstance(value, bool):
|
|
227
|
+
return TypeSpec(BaseType.BOOL)
|
|
228
|
+
|
|
229
|
+
if isinstance(value, int):
|
|
230
|
+
return TypeSpec(BaseType.INT)
|
|
231
|
+
|
|
232
|
+
if isinstance(value, float):
|
|
233
|
+
return TypeSpec(BaseType.FLOAT)
|
|
234
|
+
|
|
235
|
+
if isinstance(value, str):
|
|
236
|
+
return TypeSpec(BaseType.STRING)
|
|
237
|
+
|
|
238
|
+
if isinstance(value, list):
|
|
239
|
+
if len(value) == 0:
|
|
240
|
+
return TypeSpec(BaseType.ARRAY, array_of=TypeSpec(BaseType.ANY))
|
|
241
|
+
|
|
242
|
+
# Infer element type from first element (simplified)
|
|
243
|
+
element_type = TypeInferencer.infer_type(value[0])
|
|
244
|
+
return TypeSpec(BaseType.ARRAY, array_of=element_type)
|
|
245
|
+
|
|
246
|
+
if isinstance(value, dict):
|
|
247
|
+
schema = {}
|
|
248
|
+
for key, val in value.items():
|
|
249
|
+
schema[key] = TypeInferencer.infer_type(val)
|
|
250
|
+
return TypeSpec(BaseType.OBJECT, object_schema=schema)
|
|
251
|
+
|
|
252
|
+
if callable(value):
|
|
253
|
+
return TypeSpec(BaseType.ACTION)
|
|
254
|
+
|
|
255
|
+
return TypeSpec(BaseType.ANY)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
class FunctionSignature:
|
|
259
|
+
"""Function signature with parameter and return types."""
|
|
260
|
+
|
|
261
|
+
def __init__(self, name: str, parameters: Dict[str, TypeSpec],
|
|
262
|
+
return_type: Optional[TypeSpec] = None):
|
|
263
|
+
"""
|
|
264
|
+
Initialize function signature.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
name: Function name
|
|
268
|
+
parameters: Dict of param_name -> TypeSpec
|
|
269
|
+
return_type: Expected return type (None = any)
|
|
270
|
+
"""
|
|
271
|
+
self.name = name
|
|
272
|
+
self.parameters = parameters
|
|
273
|
+
self.return_type = return_type or TypeSpec(BaseType.ANY)
|
|
274
|
+
|
|
275
|
+
def __str__(self) -> str:
|
|
276
|
+
"""String representation."""
|
|
277
|
+
params = ", ".join(f"{k}:{v}" for k, v in self.parameters.items())
|
|
278
|
+
return f"action {self.name}({params}) -> {self.return_type}"
|
|
279
|
+
|
|
280
|
+
def validate_call(self, args: Dict[str, Any], checker: TypeChecker) -> Tuple[bool, List[str]]:
|
|
281
|
+
"""
|
|
282
|
+
Validate arguments for a function call.
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
(valid: bool, errors: [str])
|
|
286
|
+
"""
|
|
287
|
+
errors = []
|
|
288
|
+
|
|
289
|
+
# Check all parameters are provided
|
|
290
|
+
for param_name, param_type in self.parameters.items():
|
|
291
|
+
if param_name not in args:
|
|
292
|
+
errors.append(f"Missing parameter '{param_name}' of type {param_type}")
|
|
293
|
+
else:
|
|
294
|
+
matches, reason = checker.check_type(args[param_name], param_type)
|
|
295
|
+
if not matches:
|
|
296
|
+
errors.append(f"Parameter '{param_name}': {reason}")
|
|
297
|
+
|
|
298
|
+
# Check no extra parameters
|
|
299
|
+
for arg_name in args:
|
|
300
|
+
if arg_name not in self.parameters:
|
|
301
|
+
errors.append(f"Unexpected parameter '{arg_name}'")
|
|
302
|
+
|
|
303
|
+
return len(errors) == 0, errors
|
|
304
|
+
|
|
305
|
+
def validate_return(self, value: Any, checker: TypeChecker) -> Tuple[bool, str]:
|
|
306
|
+
"""Validate return value."""
|
|
307
|
+
return checker.check_type(value, self.return_type)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
# Standard type definitions
|
|
311
|
+
|
|
312
|
+
STANDARD_TYPES = {
|
|
313
|
+
"bool": TypeSpec(BaseType.BOOL),
|
|
314
|
+
"int": TypeSpec(BaseType.INT),
|
|
315
|
+
"float": TypeSpec(BaseType.FLOAT),
|
|
316
|
+
"string": TypeSpec(BaseType.STRING),
|
|
317
|
+
"array": TypeSpec(BaseType.ARRAY),
|
|
318
|
+
"object": TypeSpec(BaseType.OBJECT),
|
|
319
|
+
"action": TypeSpec(BaseType.ACTION),
|
|
320
|
+
"any": TypeSpec(BaseType.ANY),
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def parse_type_annotation(annotation: str) -> Optional[TypeSpec]:
|
|
325
|
+
"""
|
|
326
|
+
Parse a type annotation string.
|
|
327
|
+
|
|
328
|
+
Examples:
|
|
329
|
+
"int" -> int
|
|
330
|
+
"string?" -> nullable string
|
|
331
|
+
"[int]" -> array of int
|
|
332
|
+
"{name:string, age:int}" -> object with schema
|
|
333
|
+
"""
|
|
334
|
+
annotation = annotation.strip()
|
|
335
|
+
|
|
336
|
+
# Check nullable
|
|
337
|
+
nullable = annotation.endswith("?")
|
|
338
|
+
if nullable:
|
|
339
|
+
annotation = annotation[:-1].strip()
|
|
340
|
+
|
|
341
|
+
# Check array
|
|
342
|
+
if annotation.startswith("[") and annotation.endswith("]"):
|
|
343
|
+
inner = annotation[1:-1].strip()
|
|
344
|
+
inner_type = parse_type_annotation(inner)
|
|
345
|
+
if inner_type:
|
|
346
|
+
return TypeSpec(BaseType.ARRAY, nullable=nullable, array_of=inner_type)
|
|
347
|
+
return None
|
|
348
|
+
|
|
349
|
+
# Check object schema
|
|
350
|
+
if annotation.startswith("{") and annotation.endswith("}"):
|
|
351
|
+
# Simplified: assume simple fields like {name:string, age:int}
|
|
352
|
+
inner = annotation[1:-1].strip()
|
|
353
|
+
if not inner:
|
|
354
|
+
return TypeSpec(BaseType.OBJECT, nullable=nullable, object_schema={})
|
|
355
|
+
|
|
356
|
+
schema = {}
|
|
357
|
+
for field_str in inner.split(","):
|
|
358
|
+
if ":" not in field_str:
|
|
359
|
+
return None
|
|
360
|
+
field_name, field_type_str = field_str.split(":", 1)
|
|
361
|
+
field_type = parse_type_annotation(field_type_str.strip())
|
|
362
|
+
if field_type:
|
|
363
|
+
schema[field_name.strip()] = field_type
|
|
364
|
+
|
|
365
|
+
return TypeSpec(BaseType.OBJECT, nullable=nullable, object_schema=schema)
|
|
366
|
+
|
|
367
|
+
# Check standard types
|
|
368
|
+
if annotation in STANDARD_TYPES:
|
|
369
|
+
return TypeSpec(
|
|
370
|
+
STANDARD_TYPES[annotation].base_type,
|
|
371
|
+
nullable=nullable
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
return None
|