Files
zen/core/expression/tests/data/analysis/inspect.toml
T
stefan-gorules ffdfd807d1 feat: implement slots instead of natural language (#527)
* feat: implement slots instead of natural language

Replace the natural-language projection (`nl`) with engine-owned slot
completion: for a cursor position the engine classifies the slot being
edited (operand, operator, literal, member access, ...) and returns typed
options, literal facts and the expected type, for policies and graphs.

- zen-expression: new `slot` module (classification, literals, operators)
  and a lenient lexer mode for incomplete input; `nl` removed
- Intellisense: typed diagnostic codes with arguments, richer inspect for
  hover, dedicated parser error variants (messages unchanged)
- Engine: `Workspace::cursor_scope`, `slot`, `facts`; `rename_from` and
  `references_from`; editor spans in UTF-16 units; renames reach imported
  policies, `$nodes` reads, child graphs and output column heads; no `$root`
  completion in policies
- Node bindings: `slot`, `facts`, `cursorScope`, `slotBatch` replace
  `nl`, `nlTokenize`, `nlEncodeString`, `nlTokenizeBatch`

No change to expression evaluation: the VM, compiler, functions and the
default lexer path are untouched, and parser error messages keep their text.

* fix: harden slot classification, scopes and graph expectations

- restore master execution order; slot scopes hide writes of the edited
  block and its dependents instead of relying on block ranking
- token-start editing gated by slot state; operator, list and operand
  spans no longer splice into neighbouring tokens
- interval-aware bracket pairing for half-open and reversed intervals
- lenient lexer recovers from unknown characters (slots only)
- graph expected type follows switch and pass-through nodes and merges
  compatible output schemas
- sibling inference caps distinct values and analyses lazily
- deterministic overload return type display

* fix: order policy blocks by entity reads through closures and relationships

- record reads for `#.field` in closures so entity fields read through
  lists become dependencies
- link reads through derived lists (filter/map results) to the entity
  fields they carry and order the list after those fields
- evaluate entity blocks on single relationships, and demand entity
  paths for plain reads through relationships
- slot scopes keep the top-level variable when hiding written fields
2026-09-28 21:47:40 +02:00

103 lines
1.9 KiB
TOML

# Inspect tests — type info at cursor position
# label: the source text at the inspected span
# kind: JSON-serialized VariableType
[[test]]
name = "identifier"
expression = "price"
pos = 2
input = '{"price": 42}'
label = "price"
kind = '"Number"'
[[test]]
name = "member - on identifier part"
expression = "customer.firstName"
pos = 4
input = '{"customer": {"firstName": "John"}}'
label = "customer"
[[test]]
name = "member - on property part"
expression = "customer.firstName"
pos = 10
input = '{"customer": {"firstName": "John"}}'
label = "firstName"
[[test]]
name = "number literal"
expression = "42"
pos = 1
label = "42"
kind = '"Number"'
[[test]]
name = "string literal"
expression = "'hello'"
pos = 3
label = "'hello'"
[[test]]
name = "binary left operand"
expression = "a + b"
pos = 0
input = '{"a": 1, "b": 2}'
label = "a"
kind = '"Number"'
[[test]]
name = "binary right operand"
expression = "a + b"
pos = 4
input = '{"a": 1, "b": 2}'
label = "b"
kind = '"Number"'
[[test]]
name = "member - property resolves to its type"
expression = "customer.firstName"
pos = 12
input = '{"customer": {"firstName": "John"}}'
label = "firstName"
kind = '"String"'
[[test]]
name = "member - incomplete expression"
expression = "customer.age >"
pos = 10
input = '{"customer": {"age": 30}}'
label = "age"
kind = '"Number"'
[[test]]
name = "function - signature and return type"
expression = "upper(name)"
pos = 1
input = '{"name": "x"}'
label = "upper"
kind = '"String"'
detail = "(str: string) -> string"
[[test]]
name = "method - signature"
expression = "d('2024-01-01').year()"
pos = 17
label = "year"
detail = "() -> number"
[[test]]
name = "string body is not a name"
expression = "customer == 'customer'"
pos = 15
input = '{"customer": "x"}'
label = "'customer'"
[[test]]
name = "unary - context reference"
expression = "$ > 10"
pos = 0
input = '{"$": 5}'
unary = true
label = "$"
kind = '"Number"'