Add types.sx gradual type system spec module with 44 tests
Implements subtype checking, type inference, type narrowing, and component call-site checking. All type logic is in types.sx (spec), bootstrapped to every host. Adds test-types.sx with full coverage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -262,6 +262,7 @@ SPECS = {
|
||||
"engine": {"file": "test-engine.sx", "needs": []},
|
||||
"orchestration": {"file": "test-orchestration.sx", "needs": []},
|
||||
"signals": {"file": "test-signals.sx", "needs": ["make-signal"]},
|
||||
"types": {"file": "test-types.sx", "needs": []},
|
||||
}
|
||||
|
||||
REF_DIR = os.path.join(_HERE, "..", "ref")
|
||||
@@ -722,6 +723,78 @@ def _load_signals(env):
|
||||
env["batch"] = _batch
|
||||
|
||||
|
||||
def _load_types(env):
|
||||
"""Load types.sx spec — gradual type system."""
|
||||
from shared.sx.types import Component
|
||||
|
||||
def _component_param_types(c):
|
||||
return getattr(c, 'param_types', None)
|
||||
|
||||
def _component_set_param_types(c, d):
|
||||
c.param_types = d
|
||||
|
||||
env["component-param-types"] = _component_param_types
|
||||
env["component-set-param-types!"] = _component_set_param_types
|
||||
|
||||
# test-prim-types: a minimal type registry for testing
|
||||
def _test_prim_types():
|
||||
return {
|
||||
"+": "number", "-": "number", "*": "number", "/": "number",
|
||||
"mod": "number", "abs": "number", "floor": "number",
|
||||
"ceil": "number", "round": "number", "min": "number",
|
||||
"max": "number", "parse-int": "number", "parse-float": "number",
|
||||
"=": "boolean", "!=": "boolean", "<": "boolean", ">": "boolean",
|
||||
"<=": "boolean", ">=": "boolean",
|
||||
"str": "string", "string-length": "number",
|
||||
"substring": "string", "upcase": "string", "downcase": "string",
|
||||
"trim": "string", "split": "list", "join": "string",
|
||||
"string-contains?": "boolean", "starts-with?": "boolean",
|
||||
"ends-with?": "boolean", "replace": "string",
|
||||
"not": "boolean", "nil?": "boolean", "number?": "boolean",
|
||||
"string?": "boolean", "list?": "boolean", "dict?": "boolean",
|
||||
"boolean?": "boolean", "symbol?": "boolean", "empty?": "boolean",
|
||||
"list": "list", "first": "any", "rest": "list", "nth": "any",
|
||||
"last": "any", "cons": "list", "append": "list",
|
||||
"reverse": "list", "len": "number", "contains?": "boolean",
|
||||
"flatten": "list", "concat": "list", "slice": "list",
|
||||
"range": "list", "sort": "list", "sort-by": "list",
|
||||
"map": "list", "filter": "list", "reduce": "any",
|
||||
"some": "boolean", "every?": "boolean",
|
||||
"dict": "dict", "assoc": "dict", "dissoc": "dict",
|
||||
"get": "any", "keys": "list", "vals": "list",
|
||||
"has-key?": "boolean", "merge": "dict",
|
||||
}
|
||||
|
||||
env["test-prim-types"] = _test_prim_types
|
||||
env["test-env"] = lambda: env
|
||||
|
||||
# Try bootstrapped types first, fall back to eval
|
||||
try:
|
||||
from shared.sx.ref.sx_ref import (
|
||||
subtype_p, type_union, narrow_type,
|
||||
infer_type, check_component_call, check_component,
|
||||
check_all, build_type_registry, type_any_p,
|
||||
type_never_p, type_nullable_p, nullable_base,
|
||||
narrow_exclude_nil, narrow_exclude,
|
||||
)
|
||||
env["subtype?"] = subtype_p
|
||||
env["type-union"] = type_union
|
||||
env["narrow-type"] = narrow_type
|
||||
env["infer-type"] = infer_type
|
||||
env["check-component-call"] = check_component_call
|
||||
env["check-component"] = check_component
|
||||
env["check-all"] = check_all
|
||||
env["build-type-registry"] = build_type_registry
|
||||
env["type-any?"] = type_any_p
|
||||
env["type-never?"] = type_never_p
|
||||
env["type-nullable?"] = type_nullable_p
|
||||
env["nullable-base"] = nullable_base
|
||||
env["narrow-exclude-nil"] = narrow_exclude_nil
|
||||
env["narrow-exclude"] = narrow_exclude
|
||||
except ImportError:
|
||||
eval_file("types.sx", env)
|
||||
|
||||
|
||||
def main():
|
||||
global passed, failed, test_num
|
||||
|
||||
@@ -769,6 +842,8 @@ def main():
|
||||
_load_orchestration(env)
|
||||
if spec_name == "signals":
|
||||
_load_signals(env)
|
||||
if spec_name == "types":
|
||||
_load_types(env)
|
||||
|
||||
print(f"# --- {spec_name} ---")
|
||||
eval_file(spec["file"], env)
|
||||
|
||||
Reference in New Issue
Block a user